# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: mhameed@src.gnome.org-20110617175131-bedrt25np5iqe292
# target_branch: http://bzr.nvaccess.org/nvda/main/
# testament_sha1: 3fa1351abd7ce46aa600cc7aa8d5a6f7e23826ab
# timestamp: 2011-06-17 18:54:16 +0100
# base_revision_id: mick@kulgan.net-20110617134937-u3suxyf54cnh2978
# 
# Begin patch
=== modified file 'source/NVDAObjects/IAccessible/__init__.py'
--- source/NVDAObjects/IAccessible/__init__.py	2011-06-16 06:51:11 +0000
+++ source/NVDAObjects/IAccessible/__init__.py	2011-06-17 11:59:40 +0000
@@ -1,6 +1,6 @@
 #NVDAObjects/IAccessible.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -1173,10 +1173,10 @@
 		if self in api.getFocusAncestors():
 			return
 		speech.cancelSpeech()
-		speech.speakObject(self, reason=speech.REASON_FOCUS)
+		speech.speakObject(self, reason=controlTypes.REASON_FOCUS)
 		for child in self.recursiveDescendants:
 			if controlTypes.STATE_FOCUSABLE in child.states:
-				speech.speakObject(child, reason=speech.REASON_FOCUS)
+				speech.speakObject(child, reason=controlTypes.REASON_FOCUS)
 
 	def event_caret(self):
 		super(IAccessible, self).event_caret()
@@ -1227,7 +1227,7 @@
 			h=hash(child)
 			if h not in hashList:
 				hashList.append(h)
-				speech.speakObject(child,reason=speech.REASON_FOCUS)
+				speech.speakObject(child,reason=controlTypes.REASON_FOCUS)
 				child.speakDescendantObjects(hashList=hashList)
 			child=child.next
 
@@ -1376,7 +1376,7 @@
 	def event_show(self):
 		# TODO: Abstract this somehow.
 		if (config.conf["presentation"]["reportTooltips"] and (self.IAccessibleRole==oleacc.ROLE_SYSTEM_TOOLTIP)) or (config.conf["presentation"]["reportHelpBalloons"] and (self.IAccessibleRole==oleacc.ROLE_SYSTEM_HELPBALLOON)):
-			speech.speakObject(self,reason=speech.REASON_FOCUS)
+			speech.speakObject(self,reason=controlTypes.REASON_FOCUS)
 			# TODO: Don't use getBrailleTextForProperties directly.
 			braille.handler.message(braille.getBrailleTextForProperties(name=self.name, role=self.role))
 
@@ -1388,21 +1388,21 @@
 	def speakDescendantObjects(self,hashList=None):
 		child=self.activeChild
 		if child:
-			speech.speakObject(child,reason=speech.REASON_FOCUS)
+			speech.speakObject(child,reason=controlTypes.REASON_FOCUS)
 
 class ComboBox(IAccessible):
 
 	def speakDescendantObjects(self,hashList=None):
 		child=self.activeChild
 		if child:
-			speech.speakObject(child,reason=speech.REASON_FOCUS)
+			speech.speakObject(child,reason=controlTypes.REASON_FOCUS)
 
 class Outline(IAccessible):
 
 	def speakDescendantObjects(self,hashList=None):
 		child=self.activeChild
 		if child:
-			speech.speakObject(child,reason=speech.REASON_FOCUS)
+			speech.speakObject(child,reason=controlTypes.REASON_FOCUS)
 
 class SysLinkClient(IAccessible):
 

=== modified file 'source/NVDAObjects/UIA/__init__.py'
--- source/NVDAObjects/UIA/__init__.py	2011-06-15 23:48:21 +0000
+++ source/NVDAObjects/UIA/__init__.py	2011-06-17 11:59:40 +0000
@@ -1,3 +1,9 @@
+#NVDAObjects/UIA.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
 from ctypes.wintypes import POINT
 from comtypes import COMError
 import weakref
@@ -500,7 +506,7 @@
 	def event_valueChange(self):
 		focusParent=api.getFocusObject().parent
 		if self==focusParent:
-			speech.speakObjectProperties(self,value=True,reason=speech.REASON_CHANGE)
+			speech.speakObjectProperties(self,value=True,reason=controlTypes.REASON_CHANGE)
 		else:
 			super(SensitiveSlider,self).event_valueChange()
 

=== modified file 'source/NVDAObjects/__init__.py'
--- source/NVDAObjects/__init__.py	2011-06-14 02:25:45 +0000
+++ source/NVDAObjects/__init__.py	2011-06-17 11:59:40 +0000
@@ -1,6 +1,6 @@
 #NVDAObjects/baseType.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -726,7 +726,7 @@
 	def reportFocus(self):
 		"""Announces this object in a way suitable such that it gained focus.
 		"""
-		speech.speakObject(self,reason=speech.REASON_FOCUS)
+		speech.speakObject(self,reason=controlTypes.REASON_FOCUS)
 
 	def event_typedCharacter(self,ch):
 		speech.speakTypedCharacters(ch)
@@ -768,7 +768,7 @@
 
 	def event_stateChange(self):
 		if self is api.getFocusObject():
-			speech.speakObjectProperties(self,states=True, reason=speech.REASON_CHANGE)
+			speech.speakObjectProperties(self,states=True, reason=controlTypes.REASON_CHANGE)
 		braille.handler.handleUpdate(self)
 
 	def event_focusEntered(self):
@@ -776,7 +776,7 @@
 			speech.cancelSpeech()
 			return
 		if self.isPresentableFocusAncestor:
-			speech.speakObject(self,reason=speech.REASON_FOCUSENTERED)
+			speech.speakObject(self,reason=controlTypes.REASON_FOCUSENTERED)
 
 	def event_gainFocus(self):
 		"""
@@ -799,17 +799,17 @@
 
 	def event_valueChange(self):
 		if self is api.getFocusObject():
-			speech.speakObjectProperties(self, value=True, reason=speech.REASON_CHANGE)
+			speech.speakObjectProperties(self, value=True, reason=controlTypes.REASON_CHANGE)
 		braille.handler.handleUpdate(self)
 
 	def event_nameChange(self):
 		if self is api.getFocusObject():
-			speech.speakObjectProperties(self, name=True, reason=speech.REASON_CHANGE)
+			speech.speakObjectProperties(self, name=True, reason=controlTypes.REASON_CHANGE)
 		braille.handler.handleUpdate(self)
 
 	def event_descriptionChange(self):
 		if self is api.getFocusObject():
-			speech.speakObjectProperties(self, description=True, reason=speech.REASON_CHANGE)
+			speech.speakObjectProperties(self, description=True, reason=controlTypes.REASON_CHANGE)
 		braille.handler.handleUpdate(self)
 
 	def event_caret(self):

=== modified file 'source/NVDAObjects/window/winword.py'
--- source/NVDAObjects/window/winword.py	2011-06-13 01:11:48 +0000
+++ source/NVDAObjects/window/winword.py	2011-06-17 11:59:40 +0000
@@ -1,6 +1,6 @@
 #appModules/winword.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -386,7 +386,7 @@
 		info=self.makeTextInfo(textInfos.POSITION_CARET)
 		if info._rangeObj.tables.count>0:
 			info.expand(textInfos.UNIT_LINE)
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 
 	def script_nextRow(self,gesture):
 		info=self.makeTextInfo("caret")
@@ -396,7 +396,7 @@
 		if info._moveInTable(0,1):
 			info.updateCaret()
 			info.expand(textInfos.UNIT_CELL)
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 		else:
 			speech.speakMessage(_("edge of table"))
 
@@ -408,7 +408,7 @@
 		if info._moveInTable(0,-1):
 			info.updateCaret()
 			info.expand(textInfos.UNIT_CELL)
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 		else:
 			speech.speakMessage(_("edge of table"))
 
@@ -420,7 +420,7 @@
 		if info._moveInTable(1,0):
 			info.updateCaret()
 			info.expand(textInfos.UNIT_CELL)
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 		else:
 			speech.speakMessage(_("edge of table"))
 
@@ -432,7 +432,7 @@
 		if info._moveInTable(-1,0):
 			info.updateCaret()
 			info.expand(textInfos.UNIT_CELL)
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 		else:
 			speech.speakMessage(_("edge of table"))
 

=== modified file 'source/api.py'
--- source/api.py	2011-05-25 10:24:32 +0000
+++ source/api.py	2011-06-17 12:47:46 +0000
@@ -1,6 +1,6 @@
 #api.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -78,7 +78,7 @@
 			safetyCount+=1
 		else:
 			try:
-				log.error("Never ending focus ancestry: last object: %s, %s, window class %s, application name %s"%(tempObj.name,controlTypes.speechRoleLabels[tempObj.role],tempObj.windowClassName,tempObj.appModule.appName))
+				log.error("Never ending focus ancestry: last object: %s, %s, window class %s, application name %s"%(tempObj.name,controlTypes.labels[tempObj.role],tempObj.windowClassName,tempObj.appModule.appName))
 			except:
 				pass
 			tempObj=getDesktopObject()

=== modified file 'source/appModules/firefox.py'
--- source/appModules/firefox.py	2010-11-26 07:31:58 +0000
+++ source/appModules/firefox.py	2011-06-17 12:47:46 +0000
@@ -1,6 +1,6 @@
 #appModules/firefox.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -18,7 +18,7 @@
 			if statusBar:
 				statusText = api.getStatusBarText(statusBar)
 				speech.cancelSpeech()
-				speech.speakMessage(controlTypes.speechStateLabels[controlTypes.STATE_BUSY])
+				speech.speakMessage(controlTypes.stateLabels[controlTypes.STATE_BUSY])
 				speech.speakMessage(statusText)
 				return
 		nextHandler()

=== modified file 'source/appModules/miranda32.py'
--- source/appModules/miranda32.py	2011-02-03 06:00:43 +0000
+++ source/appModules/miranda32.py	2011-06-17 11:59:40 +0000
@@ -1,6 +1,6 @@
 #appModules/miranda32.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -161,7 +161,7 @@
 		gesture.send()
 		if not isScriptWaiting():
 			api.processPendingEvents()
-			speech.speakObject(self,reason=speech.REASON_FOCUS)
+			speech.speakObject(self,reason=controlTypes.REASON_FOCUS)
 			braille.handler.handleGainFocus(self)
 
 	__changeItemGestures = (

=== modified file 'source/appModules/msimn.py'
--- source/appModules/msimn.py	2011-06-15 04:29:22 +0000
+++ source/appModules/msimn.py	2011-06-17 12:47:46 +0000
@@ -1,6 +1,6 @@
 #appModules/msimn.py - Outlook Express appModule
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2010 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -87,9 +87,9 @@
 		nameList=[]
 		imageState=winUser.sendMessage(self.windowHandle,sysListView32.LVM_GETITEMSTATE,self.IAccessibleChildID-1,sysListView32.LVIS_STATEIMAGEMASK)>>12
 		if imageState==5:
-			nameList.append(controlTypes.speechStateLabels[controlTypes.STATE_COLLAPSED])
+			nameList.append(controlTypes.stateLabels[controlTypes.STATE_COLLAPSED])
 		elif imageState==6:
-			nameList.append(controlTypes.speechStateLabels[controlTypes.STATE_EXPANDED])
+			nameList.append(controlTypes.stateLabels[controlTypes.STATE_EXPANDED])
 		if self.isUnread:
 			nameList.append(_("unread"))
 		name=super(MessageListItem,self).name

=== modified file 'source/appModules/thunderbird.py'
--- source/appModules/thunderbird.py	2010-11-26 07:31:58 +0000
+++ source/appModules/thunderbird.py	2011-06-17 12:47:46 +0000
@@ -1,6 +1,6 @@
 #appModules/thunderbird.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -22,7 +22,7 @@
 				except:
 					# Fall back to reading the entire status bar.
 					statusText = api.getStatusBarText(statusBar)
-				speech.speakMessage(controlTypes.speechStateLabels[controlTypes.STATE_BUSY])
+				speech.speakMessage(controlTypes.stateLabels[controlTypes.STATE_BUSY])
 				speech.speakMessage(statusText)
 				return
 		nextHandler()

=== modified file 'source/appModules/totalcmd.py'
--- source/appModules/totalcmd.py	2010-11-26 07:31:58 +0000
+++ source/appModules/totalcmd.py	2011-06-17 12:47:46 +0000
@@ -1,6 +1,6 @@
 #appModules/totalcmd.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -41,7 +41,7 @@
 		if self.name:
 			speakList=[]
 			if controlTypes.STATE_SELECTED in self.states:
-				speakList.append(controlTypes.speechStateLabels[controlTypes.STATE_SELECTED])
+				speakList.append(controlTypes.stateLabels[controlTypes.STATE_SELECTED])
 			speakList.append(self.name.split("\\")[-1])
 			speech.speakMessage(" ".join(speakList))
 		else:

=== modified file 'source/appModules/winamp.py'
--- source/appModules/winamp.py	2010-11-26 07:31:58 +0000
+++ source/appModules/winamp.py	2011-06-17 11:59:40 +0000
@@ -1,6 +1,6 @@
 #appModules/winamp.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2010 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -115,7 +115,7 @@
 		gesture.send()
 		if not isScriptWaiting():
 			api.processPendingEvents()
-			speech.speakObject(self,reason=speech.REASON_FOCUS)
+			speech.speakObject(self,reason=controlTypes.REASON_FOCUS)
 
 	def event_nameChange(self):
 		return super(winampMainWindow,self).event_nameChange()

=== modified file 'source/braille.py'
--- source/braille.py	2011-06-06 11:25:07 +0000
+++ source/braille.py	2011-06-17 17:51:31 +0000
@@ -73,7 +73,7 @@
 	("zh-tw.ctb", _("Chinese (Taiwan, Mandarin)")),
 )
 
-roleLabels = {
+labels = {
 	controlTypes.ROLE_EDITABLETEXT: _("edt"),
 	controlTypes.ROLE_LIST: _("lst"),
 	controlTypes.ROLE_MENUBAR: _("mnubar"),
@@ -90,8 +90,13 @@
 
 positiveStateLabels = {
 	controlTypes.STATE_CHECKED: _("(x)"),
+	controlTypes.STATE_HALFCHECKED:_("(-)"),
 	controlTypes.STATE_SELECTED: _("sel"),
 	controlTypes.STATE_HASPOPUP: _("submnu"),
+	controlTypes.STATE_AUTOCOMPLETE:_("..."),
+	controlTypes.STATE_EXPANDED:_("-"),
+	controlTypes.STATE_COLLAPSED:_("+"),
+	controlTypes.STATE_READONLY:_("rdedt"),
 }
 negativeStateLabels = {
 	controlTypes.STATE_CHECKED: _("( )"),
@@ -209,22 +214,22 @@
 		textList.append(name)
 	role = propertyValues.get("role")
 	if role is not None:
-		if name and role in speech.silentRolesOnFocus:
+		if name and role in controlTypes.ignoreRolesOnFocus:
 			roleText = None
 		else:
-			roleText = roleLabels.get(role, controlTypes.speechRoleLabels[role])
+			roleText = labels.get(role, controlTypes.labels[role])
 	else:
 		role = propertyValues.get("_role")
 		roleText = None
 	value = propertyValues.get("value")
-	if value and role not in speech.silentValuesForRoles:
+	if value and role not in controlTypes.ignoreValuesForRoles:
 		textList.append(value)
 	states = propertyValues.get("states")
 	if states:
-		positiveStates = speech.processPositiveStates(role, states, speech.REASON_FOCUS, states)
-		textList.extend(positiveStateLabels.get(state, controlTypes.speechStateLabels[state]) for state in positiveStates)
-		negativeStates = speech.processNegativeStates(role, states, speech.REASON_FOCUS, None)
-		textList.extend(negativeStateLabels.get(state, _("not %s") % controlTypes.speechStateLabels[state]) for state in negativeStates)
+		positiveStates = controlTypes.processPositiveStates(role, states, controlTypes.REASON_FOCUS, states)
+		textList.extend(positiveStateLabels.get(state, controlTypes.stateLabels[state]) for state in positiveStates)
+		negativeStates = controlTypes.processNegativeStates(role, states, controlTypes.REASON_FOCUS, None)
+		textList.extend(negativeStateLabels.get(state, _("not %s") % controlTypes.stateLabels[state]) for state in negativeStates)
 	if roleText:
 		textList.append(roleText)
 	description = propertyValues.get("description")

=== modified file 'source/compoundDocuments.py'
--- source/compoundDocuments.py	2010-10-26 06:46:03 +0000
+++ source/compoundDocuments.py	2011-06-17 11:59:40 +0000
@@ -2,7 +2,7 @@
 #A part of NonVisual Desktop Access (NVDA)
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
-#Copyright (C) 2010 James Teh <jamie@jantrid.net>
+#Copyright (C) 2010-2011 James Teh <jamie@jantrid.net>
 
 import winUser
 import textInfos
@@ -388,7 +388,7 @@
 		return eventHandler.lastQueuedFocusObject
 
 	def event_treeInterceptor_gainFocus(self):
-		speech.speakObject(self.rootNVDAObject, reason=speech.REASON_FOCUS)
+		speech.speakObject(self.rootNVDAObject, reason=controlTypes.REASON_FOCUS)
 		try:
 			info = self.makeTextInfo(textInfos.POSITION_SELECTION)
 		except RuntimeError:

=== modified file 'source/controlTypes.py'
--- source/controlTypes.py	2011-05-16 04:47:10 +0000
+++ source/controlTypes.py	2011-06-17 12:47:46 +0000
@@ -1,3 +1,8 @@
+#controlTypes.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
 
 ROLE_UNKNOWN=0
 ROLE_WINDOW=1
@@ -178,7 +183,7 @@
 STATE_SORTED_DESCENDING=0x200000000
 STATES_SORTED=frozenset([STATE_SORTED,STATE_SORTED_ASCENDING,STATE_SORTED_DESCENDING])
 
-speechRoleLabels={
+labels={
 	ROLE_UNKNOWN:_("unknown"),
 	ROLE_WINDOW:_("window"),
 	ROLE_TITLEBAR:_("title bar"),
@@ -323,7 +328,7 @@
 	ROLE_CALENDAR:_("calendar"),
 }
 
-speechStateLabels={
+stateLabels={
 	STATE_UNAVAILABLE:_("unavailable"),
 	STATE_FOCUSED:_("focused"),
 	STATE_SELECTED:_("selected"),
@@ -359,3 +364,103 @@
 	STATE_SORTED_ASCENDING:_("sorted ascending"),
 	STATE_SORTED_DESCENDING:_("sorted descending"),
 }
+
+ignoreRolesOnFocus=set([
+	ROLE_PANE,
+	ROLE_ROOTPANE,
+	ROLE_FRAME,
+	ROLE_UNKNOWN,
+	ROLE_APPLICATION,
+	ROLE_TABLECELL,
+	ROLE_LISTITEM,
+	ROLE_MENUITEM,
+	ROLE_CHECKMENUITEM,
+	ROLE_TREEVIEWITEM,
+])
+
+ignoreValuesForRoles=set([
+	ROLE_CHECKBOX,
+	ROLE_RADIOBUTTON,
+	ROLE_LINK,
+	ROLE_MENUITEM,
+	ROLE_APPLICATION,
+])
+
+# Reason constants, to determine why information is required, enables us to provide different information depending 
+# on an object is being focused, the user specifically requested information via a query etc.
+REASON_FOCUS=1
+REASON_MOUSE=2
+REASON_QUERY=3
+REASON_CHANGE=4
+REASON_MESSAGE=5
+REASON_SAYALL=6
+REASON_CARET=7
+REASON_DEBUG=8
+REASON_ONLYCACHE=9
+REASON_FOCUSENTERED=10
+
+def processPositiveStates(role, states, reason, positiveStates):
+	positiveStates = positiveStates.copy()
+	# The user never cares about certain states.
+	if role==ROLE_EDITABLETEXT:
+		positiveStates.discard(STATE_EDITABLE)
+	if role!=ROLE_LINK:
+		positiveStates.discard(STATE_VISITED)
+	positiveStates.discard(STATE_SELECTABLE)
+	positiveStates.discard(STATE_FOCUSABLE)
+	positiveStates.discard(STATE_CHECKABLE)
+	if STATE_DRAGGING in positiveStates:
+		# It's obvious that the control is draggable if it's being dragged.
+		positiveStates.discard(STATE_DRAGGABLE)
+	if role == ROLE_COMBOBOX:
+		# Combo boxes inherently have a popup, so don't report it.
+		positiveStates.discard(STATE_HASPOPUP)
+	if reason == REASON_QUERY:
+		return positiveStates
+	positiveStates.discard(STATE_DEFUNCT)
+	positiveStates.discard(STATE_MODAL)
+	positiveStates.discard(STATE_FOCUSED)
+	positiveStates.discard(STATE_OFFSCREEN)
+	positiveStates.discard(STATE_INVISIBLE)
+	if reason != REASON_CHANGE:
+		positiveStates.discard(STATE_LINKED)
+		if role in (ROLE_LISTITEM, ROLE_TREEVIEWITEM, ROLE_MENUITEM, ROLE_TABLEROW) and STATE_SELECTABLE in states:
+			positiveStates.discard(STATE_SELECTED)
+	if role != ROLE_EDITABLETEXT:
+		positiveStates.discard(STATE_READONLY)
+	if role == ROLE_CHECKBOX:
+		positiveStates.discard(STATE_PRESSED)
+	if role == ROLE_MENUITEM:
+		# The user doesn't usually care if a menu item is expanded or collapsed.
+		positiveStates.discard(STATE_COLLAPSED)
+		positiveStates.discard(STATE_EXPANDED)
+	return positiveStates
+
+def processNegativeStates(role, states, reason, negativeStates):
+	presentNegatives = set()
+	# Add the negative selected state if the control is selectable,
+	# but only if it is either focused or this is something other than a change event.
+	# The condition stops "not selected" from being presented in some broken controls
+	# when the state change for the previous focus is issued before the focus change.
+	if role in (ROLE_LISTITEM, ROLE_TREEVIEWITEM, ROLE_TABLEROW) and STATE_SELECTABLE in states and (reason != REASON_CHANGE or STATE_FOCUSED in states):
+		presentNegatives.add(STATE_SELECTED)
+	# Restrict "not checked" in a similar way to "not selected".
+	if (role in (ROLE_CHECKBOX, ROLE_RADIOBUTTON, ROLE_CHECKMENUITEM) or STATE_CHECKABLE in states)  and (STATE_HALFCHECKED not in states) and (reason != REASON_CHANGE or STATE_FOCUSED in states):
+		presentNegatives.add(STATE_CHECKED)
+	if reason == REASON_CHANGE:
+		# We want to present this state only if it is changing to negative.
+		presentNegatives.add(STATE_DROPTARGET)
+		# We were given states which have changed to negative.
+		# Return only those supplied negative states which should be presented;
+		# i.e. the states in both sets.
+		presentNegatives &= negativeStates
+		if STATES_SORTED & negativeStates and not STATES_SORTED & states:
+			# If the object has just stopped being sorted, just report not sorted.
+			# The user doesn't care how it was sorted before.
+			presentNegatives.add(STATE_SORTED)
+		return presentNegatives
+	else:
+		# This is not a state change; only positive states were supplied.
+		# Return all negative states which should be presented, excluding the positive states.
+		return presentNegatives - states
+

=== modified file 'source/cursorManager.py'
--- source/cursorManager.py	2011-06-02 11:20:56 +0000
+++ source/cursorManager.py	2011-06-17 11:59:40 +0000
@@ -1,6 +1,6 @@
 #cursorManager.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2008 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
@@ -17,6 +17,7 @@
 import speech
 import config
 import braille
+import controlTypes
 
 class CursorManager(baseObject.ScriptableObject):
 	"""
@@ -72,7 +73,7 @@
 			info.move(unit,direction)
 		self.selection=info
 		info.expand(unit)
-		speech.speakTextInfo(info,unit=unit,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=unit,reason=controlTypes.REASON_CARET)
 		if not oldInfo.isCollapsed:
 			speech.speakSelectionChange(oldInfo,self.selection)
 
@@ -93,7 +94,7 @@
 			self.selection=info
 			speech.cancelSpeech()
 			info.move(textInfos.UNIT_LINE,1,endPoint="end")
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 		else:
 			wx.CallAfter(gui.messageBox,_('text "%s" not found')%text,_("Find Error"),wx.OK|wx.ICON_ERROR)
 		CursorManager._lastFindText=text

=== modified file 'source/editableText.py'
--- source/editableText.py	2011-01-21 06:03:30 +0000
+++ source/editableText.py	2011-06-17 11:59:40 +0000
@@ -2,7 +2,7 @@
 #A part of NonVisual Desktop Access (NVDA)
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
-#Copyright (C) 2006-2010 Michael Curran <mick@kulgan.net>, James Teh <jamie@jantrid.net>
+#Copyright (C) 2006-2011 Michael Curran <mick@kulgan.net>, James Teh <jamie@jantrid.net>
 
 """Common support for editable text.
 """
@@ -13,6 +13,7 @@
 import braille
 import speech
 import config
+import controlTypes
 import eventHandler
 from scriptHandler import isScriptWaiting
 import textInfos
@@ -65,7 +66,7 @@
 			api.setReviewPosition(info.copy())
 		if speakUnit:
 			info.expand(speakUnit)
-			speech.speakTextInfo(info, unit=speakUnit, reason=speech.REASON_CARET)
+			speech.speakTextInfo(info, unit=speakUnit, reason=controlTypes.REASON_CARET)
 
 	def _caretMovementScriptHelper(self, gesture, unit):
 		try:

=== modified file 'source/globalCommands.py'
--- source/globalCommands.py	2011-06-14 12:36:06 +0000
+++ source/globalCommands.py	2011-06-17 11:59:40 +0000
@@ -2,7 +2,7 @@
 #A part of NonVisual Desktop Access (NVDA)
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
-#Copyright (C) 2006-2010 Michael Curran <mick@kulgan.net>, James Teh <jamie@jantrid.net>, Peter Vágner <peter.v@datagate.sk>, Aleksey Sadovoy <lex@onm.su>, Rui Batista<ruiandrebatista@gmail.com>
+#Copyright (C) 2006-2011 Michael Curran <mick@kulgan.net>, James Teh <jamie@jantrid.net>, Peter Vágner <peter.v@datagate.sk>, Aleksey Sadovoy <lex@onm.su>, Rui Batista<ruiandrebatista@gmail.com>
 
 import time
 import tones
@@ -65,7 +65,7 @@
 			info=obj.makeTextInfo(textInfos.POSITION_FIRST)
 		info.expand(textInfos.UNIT_LINE)
 		if scriptHandler.getLastScriptRepeatCount()==0:
-			speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
 		else:
 			speech.speakSpelling(info.text)
 	script_reportCurrentLine.__doc__=_("Reports the current line under the application cursor. Pressing this key twice will spell the current line")
@@ -287,7 +287,7 @@
 					if api.copyToClip(text):
 						speech.speakMessage(_("%s copied to clipboard")%text)
 		else:
-			speech.speakObject(curObject,reason=speech.REASON_QUERY)
+			speech.speakObject(curObject,reason=controlTypes.REASON_QUERY)
 	script_navigatorObject_current.__doc__=_("Reports the current navigator object. Pressing twice spells this information,and pressing three times Copies name and value of this  object to the clipboard")
 
 	def script_navigatorObject_currentDimensions(self,gesture):
@@ -317,7 +317,7 @@
 			pos=obj.makeTextInfo(textInfos.POSITION_FIRST)
 		api.setReviewPosition(pos)
 		speech.speakMessage(_("move to focus"))
-		speech.speakObject(obj,reason=speech.REASON_QUERY)
+		speech.speakObject(obj,reason=controlTypes.REASON_QUERY)
 	script_navigatorObject_toFocus.__doc__=_("Sets the navigator object to the current focus, and the review cursor to the position of the caret inside it, if possible.")
 
 	def script_navigatorObject_moveFocus(self,gesture):
@@ -336,7 +336,7 @@
 				return
 			info=review.copy()
 			info.expand(textInfos.UNIT_LINE)
-			speech.speakTextInfo(info,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET)
 	script_navigatorObject_moveFocus.__doc__=_("Pressed once Sets the keyboard focus to the navigator object, pressed twice sets the system caret to the position of the review cursor")
 
 	def script_navigatorObject_parent(self,gesture):
@@ -348,7 +348,7 @@
 		curObject=curObject.simpleParent if simpleReviewMode else curObject.parent
 		if curObject is not None:
 			api.setNavigatorObject(curObject)
-			speech.speakObject(curObject,reason=speech.REASON_QUERY)
+			speech.speakObject(curObject,reason=controlTypes.REASON_QUERY)
 		else:
 			speech.speakMessage(_("No parents"))
 	script_navigatorObject_parent.__doc__=_("Moves the navigator object to the object containing it")
@@ -362,7 +362,7 @@
 		curObject=curObject.simpleNext if simpleReviewMode else curObject.next
 		if curObject is not None:
 			api.setNavigatorObject(curObject)
-			speech.speakObject(curObject,reason=speech.REASON_QUERY)
+			speech.speakObject(curObject,reason=controlTypes.REASON_QUERY)
 		else:
 			speech.speakMessage(_("No next"))
 	script_navigatorObject_next.__doc__=_("Moves the navigator object to the next object")
@@ -376,7 +376,7 @@
 		curObject=curObject.simplePrevious if simpleReviewMode else curObject.previous
 		if curObject is not None:
 			api.setNavigatorObject(curObject)
-			speech.speakObject(curObject,reason=speech.REASON_QUERY)
+			speech.speakObject(curObject,reason=controlTypes.REASON_QUERY)
 		else:
 			speech.speakMessage(_("No previous"))
 	script_navigatorObject_previous.__doc__=_("Moves the navigator object to the previous object")
@@ -390,7 +390,7 @@
 		curObject=curObject.simpleFirstChild if simpleReviewMode else curObject.firstChild
 		if curObject is not None:
 			api.setNavigatorObject(curObject)
-			speech.speakObject(curObject,reason=speech.REASON_QUERY)
+			speech.speakObject(curObject,reason=controlTypes.REASON_QUERY)
 		else:
 			speech.speakMessage(_("No children"))
 	script_navigatorObject_firstChild.__doc__=_("Moves the navigator object to the first object it contains")
@@ -418,7 +418,7 @@
 		api.setReviewPosition(info.copy())
 		info.expand(textInfos.UNIT_LINE)
 		speech.speakMessage(_("top"))
-		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
 	script_review_top.__doc__=_("Moves the review cursor to the top line of the current navigator object and speaks it")
 
 	def script_review_previousLine(self,gesture):
@@ -430,7 +430,7 @@
 		info.expand(textInfos.UNIT_LINE)
 		if res==0:
 			speech.speakMessage(_("top"))
-		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
 	script_review_previousLine.__doc__=_("Moves the review cursor to the previous line of the current navigator object and speaks it")
 
 	def script_review_currentLine(self,gesture):
@@ -438,7 +438,7 @@
 		info.expand(textInfos.UNIT_LINE)
 		scriptCount=scriptHandler.getLastScriptRepeatCount()
 		if scriptCount==0:
-			speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
 		else:
 			speech.speakSpelling(info.text,useCharacterDescriptions=bool(scriptCount>1))
 	script_review_currentLine.__doc__=_("Reports the line of the current navigator object where the review cursor is situated. If this key is pressed twice, the current line will be spelled. Pressing three times will spell the line using character descriptions.")
@@ -452,7 +452,7 @@
 		info.expand(textInfos.UNIT_LINE)
 		if res==0:
 			speech.speakMessage(_("bottom"))
-		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
 	script_review_nextLine.__doc__=_("Moves the review cursor to the next line of the current navigator object and speaks it")
 
 	def script_review_bottom(self,gesture):
@@ -460,7 +460,7 @@
 		api.setReviewPosition(info.copy())
 		info.expand(textInfos.UNIT_LINE)
 		speech.speakMessage(_("bottom"))
-		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=textInfos.UNIT_LINE,reason=controlTypes.REASON_CARET)
 	script_review_bottom.__doc__=_("Moves the review cursor to the bottom line of the current navigator object and speaks it")
 
 	def script_review_previousWord(self,gesture):
@@ -472,7 +472,7 @@
 		info.expand(textInfos.UNIT_WORD)
 		if res==0:
 			speech.speakMessage(_("top"))
-		speech.speakTextInfo(info,reason=speech.REASON_CARET,unit=textInfos.UNIT_WORD)
+		speech.speakTextInfo(info,reason=controlTypes.REASON_CARET,unit=textInfos.UNIT_WORD)
 	script_review_previousWord.__doc__=_("Moves the review cursor to the previous word of the current navigator object and speaks it")
 
 	def script_review_currentWord(self,gesture):
@@ -480,7 +480,7 @@
 		info.expand(textInfos.UNIT_WORD)
 		scriptCount=scriptHandler.getLastScriptRepeatCount()
 		if scriptCount==0:
-			speech.speakTextInfo(info,reason=speech.REASON_CARET,unit=textInfos.UNIT_WORD)
+			speech.speakTextInfo(info,reason=controlTypes.REASON_CARET,unit=textInfos.UNIT_WORD)
 		else:
 			speech.speakSpelling(info.text,useCharacterDescriptions=bool(scriptCount>1))
 	script_review_currentWord.__doc__=_("Speaks the word of the current navigator object where the review cursor is situated. If this key is pressed twice, the word will be spelled")
@@ -494,7 +494,7 @@
 		info.expand(textInfos.UNIT_WORD)
 		if res==0:
 			speech.speakMessage(_("bottom"))
-		speech.speakTextInfo(info,reason=speech.REASON_CARET,unit=textInfos.UNIT_WORD)
+		speech.speakTextInfo(info,reason=controlTypes.REASON_CARET,unit=textInfos.UNIT_WORD)
 	script_review_nextWord.__doc__=_("Moves the review cursor to the next word of the current navigator object and speaks it")
 
 	def script_review_startOfLine(self,gesture):
@@ -504,7 +504,7 @@
 		api.setReviewPosition(info.copy())
 		info.expand(textInfos.UNIT_CHARACTER)
 		speech.speakMessage(_("left"))
-		speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 	script_review_startOfLine.__doc__=_("Moves the review cursor to the first character of the line where it is situated in the current navigator object and speaks it")
 
 	def script_review_previousCharacter(self,gesture):
@@ -518,11 +518,11 @@
 			speech.speakMessage(_("left"))
 			reviewInfo=api.getReviewPosition().copy()
 			reviewInfo.expand(textInfos.UNIT_CHARACTER)
-			speech.speakTextInfo(reviewInfo,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+			speech.speakTextInfo(reviewInfo,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 		else:
 			api.setReviewPosition(charInfo.copy())
 			charInfo.expand(textInfos.UNIT_CHARACTER)
-			speech.speakTextInfo(charInfo,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+			speech.speakTextInfo(charInfo,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 	script_review_previousCharacter.__doc__=_("Moves the review cursor to the previous character of the current navigator object and speaks it")
 
 	def script_review_currentCharacter(self,gesture):
@@ -530,7 +530,7 @@
 		info.expand(textInfos.UNIT_CHARACTER)
 		scriptCount=scriptHandler.getLastScriptRepeatCount()
 		if scriptCount==0:
-			speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+			speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 		elif scriptCount==1:
 			speech.speakSpelling(info.text,useCharacterDescriptions=True)
 		else:
@@ -539,7 +539,7 @@
 				speech.speakMessage("%d," % c)
 				speech.speakSpelling(hex(c))
 			except:
-				speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+				speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 	script_review_currentCharacter.__doc__=_("Reports the character of the current navigator object where the review cursor is situated. If this key is pressed twice, ascii and hexadecimal values are spoken for the character")
 
 	def script_review_nextCharacter(self,gesture):
@@ -553,11 +553,11 @@
 			speech.speakMessage(_("right"))
 			reviewInfo=api.getReviewPosition().copy()
 			reviewInfo.expand(textInfos.UNIT_CHARACTER)
-			speech.speakTextInfo(reviewInfo,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+			speech.speakTextInfo(reviewInfo,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 		else:
 			api.setReviewPosition(charInfo.copy())
 			charInfo.expand(textInfos.UNIT_CHARACTER)
-			speech.speakTextInfo(charInfo,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+			speech.speakTextInfo(charInfo,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 	script_review_nextCharacter.__doc__=_("Moves the review cursor to the next character of the current navigator object and speaks it")
 
 	def script_review_endOfLine(self,gesture):
@@ -568,7 +568,7 @@
 		api.setReviewPosition(info.copy())
 		info.expand(textInfos.UNIT_CHARACTER)
 		speech.speakMessage(_("right"))
-		speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,unit=textInfos.UNIT_CHARACTER,reason=controlTypes.REASON_CARET)
 	script_review_endOfLine.__doc__=_("Moves the review cursor to the last character of the line where it is situated in the current navigator object and speaks it")
 
 	def script_speechMode(self,gesture):
@@ -666,7 +666,7 @@
 		focusObject=api.getFocusObject()
 		if isinstance(focusObject,NVDAObject):
 			if scriptHandler.getLastScriptRepeatCount()==0:
-				speech.speakObject(focusObject, reason=speech.REASON_QUERY)
+				speech.speakObject(focusObject, reason=controlTypes.REASON_QUERY)
 			else:
 				speech.speakSpelling(focusObject.name)
 		else:
@@ -717,7 +717,7 @@
 	def script_speakForeground(self,gesture):
 		obj=api.getForegroundObject()
 		if obj:
-			speech.speakObject(obj,reason=speech.REASON_QUERY)
+			speech.speakObject(obj,reason=controlTypes.REASON_QUERY)
 			obj.speakDescendantObjects()
 	script_speakForeground.__doc__ = _("speaks the current foreground object")
 

=== modified file 'source/inputCore.py'
--- source/inputCore.py	2011-05-29 23:18:53 +0000
+++ source/inputCore.py	2011-06-17 11:59:40 +0000
@@ -2,7 +2,7 @@
 #A part of NonVisual Desktop Access (NVDA)
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
-#Copyright (C) 2010 James Teh <jamie@jantrid.net>
+#Copyright (C) 2010-2011 James Teh <jamie@jantrid.net>
 
 import sys
 import os
@@ -15,6 +15,7 @@
 import speech
 import characterProcessing
 import config
+import controlTypes
 import watchdog
 from logHandler import log
 import globalVars
@@ -337,7 +338,7 @@
 		import braille
 		braille.handler.message("\t\t".join(textList))
 		# Punctuation must be spoken for the gesture name (the first chunk) so that punctuation keys are spoken.
-		speech.speakText(textList[0], reason=speech.REASON_MESSAGE, symbolLevel=characterProcessing.SYMLVL_ALL)
+		speech.speakText(textList[0], reason=controlTypes.REASON_MESSAGE, symbolLevel=characterProcessing.SYMLVL_ALL)
 		for text in textList[1:]:
 			speech.speakMessage(text)
 

=== modified file 'source/sayAllHandler.py'
--- source/sayAllHandler.py	2011-04-28 03:28:27 +0000
+++ source/sayAllHandler.py	2011-06-17 11:59:40 +0000
@@ -1,11 +1,12 @@
 #sayAllHandler.py
 #A part of NonVisual Desktop Access (NVDA)
-#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
 #This file is covered by the GNU General Public License.
 #See the file COPYING for more details.
 
 import queueHandler
 import config
+import controlTypes
 import speech
 import textInfos
 import globalVars
@@ -58,7 +59,7 @@
 			yield
 			continue
 		if keepReading:
-			speech.speakObject(obj,index=indexCount,reason=speech.REASON_SAYALL)
+			speech.speakObject(obj,index=indexCount,reason=controlTypes.REASON_SAYALL)
 			up=[]
 			down=[]
 			obj=obj.getNextInFlow(up=up,down=down)
@@ -117,7 +118,7 @@
 					speech.speakWithoutPauses(None)
 					keepReading=False
 					continue
-				speech.speakTextInfo(reader,unit=textInfos.UNIT_READINGCHUNK,reason=speech.REASON_SAYALL,index=index)
+				speech.speakTextInfo(reader,unit=textInfos.UNIT_READINGCHUNK,reason=controlTypes.REASON_SAYALL,index=index)
 				sendCount+=1
 				cursorIndexMap[index]=bookmark
 				reader.collapse(end=True)

=== modified file 'source/speech.py' (properties changed: +x to -x)
--- source/speech.py	2011-06-14 12:21:55 +0000
+++ source/speech.py	2011-06-17 12:47:46 +0000
@@ -34,16 +34,6 @@
 isPaused=False
 curWordChars=[]
 
-REASON_FOCUS=1
-REASON_MOUSE=2
-REASON_QUERY=3
-REASON_CHANGE=4
-REASON_MESSAGE=5
-REASON_SAYALL=6
-REASON_CARET=7
-REASON_DEBUG=8
-REASON_ONLYCACHE=9
-REASON_FOCUSENTERED=10
 
 #: The string used to separate distinct chunks of text when multiple chunks should be spoken without pauses.
 CHUNK_SEPARATOR = "  "
@@ -122,7 +112,7 @@
 @param index: the index to mark this current text with, its best to use the character position of the text if you know it 
 @type index: int
 """
-	speakText(text,index=index,reason=REASON_MESSAGE)
+	speakText(text,index=index,reason=controlTypes.REASON_MESSAGE)
 
 _speakSpellingGenID = None
 
@@ -188,7 +178,7 @@
 		if uppercase and  synthConfig["beepForCapitals"]:
 			tones.beep(2000,50)
 
-def speakObjectProperties(obj,reason=REASON_QUERY,index=None,**allowedProperties):
+def speakObjectProperties(obj,reason=controlTypes.REASON_QUERY,index=None,**allowedProperties):
 	if speechMode==speechMode_off:
 		return
 	#Fetch the values for all wanted properties
@@ -216,10 +206,10 @@
 	cachedPropertyValues.update(newPropertyValues)
 	obj._speakObjectPropertiesCache=cachedPropertyValues
 	#If we should only cache we can stop here
-	if reason==REASON_ONLYCACHE:
+	if reason==controlTypes.REASON_ONLYCACHE:
 		return
 	#If only speaking change, then filter out all values that havn't changed
-	if reason==REASON_CHANGE:
+	if reason==controlTypes.REASON_CHANGE:
 		for name in set(newPropertyValues)&set(oldCachedPropertyValues):
 			if newPropertyValues[name]==oldCachedPropertyValues[name]:
 				del newPropertyValues[name]
@@ -237,17 +227,17 @@
 	if text:
 		speakText(text,index=index)
 
-def speakObject(obj,reason=REASON_QUERY,index=None):
+def speakObject(obj,reason=controlTypes.REASON_QUERY,index=None):
 	from NVDAObjects import NVDAObjectTextInfo
-	isEditable=(reason!=REASON_FOCUSENTERED and obj.TextInfo!=NVDAObjectTextInfo and (obj.role in (controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_TERMINAL) or controlTypes.STATE_EDITABLE in obj.states))
+	isEditable=(reason!=controlTypes.REASON_FOCUSENTERED and obj.TextInfo!=NVDAObjectTextInfo and (obj.role in (controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_TERMINAL) or controlTypes.STATE_EDITABLE in obj.states))
 	allowProperties={'name':True,'role':True,'states':True,'value':True,'description':True,'keyboardShortcut':True,'positionInfo_level':True,'positionInfo_indexInGroup':True,'positionInfo_similarItemsInGroup':True,"rowNumber":True,"columnNumber":True,"columnCount":True,"rowCount":True}
 
-	if reason==REASON_FOCUSENTERED:
+	if reason==controlTypes.REASON_FOCUSENTERED:
 		allowProperties["value"]=False
 		allowProperties["keyboardShortcut"]=False
 		allowProperties["positionInfo_level"]=False
 		# Aside from excluding some properties, focus entered should be spoken like focus.
-		reason=REASON_FOCUS
+		reason=controlTypes.REASON_FOCUS
 
 	if not config.conf["presentation"]["reportObjectDescriptions"]:
 		allowProperties["description"]=False
@@ -257,7 +247,7 @@
 		allowProperties["positionInfo_level"]=False
 		allowProperties["positionInfo_indexInGroup"]=False
 		allowProperties["positionInfo_similarItemsInGroup"]=False
-	if reason!=REASON_QUERY:
+	if reason!=controlTypes.REASON_QUERY:
 		allowProperties["rowCount"]=False
 		allowProperties["columnCount"]=False
 		if (not config.conf["documentFormatting"]["reportTables"]
@@ -269,7 +259,7 @@
 		allowProperties['value']=False
 
 	speakObjectProperties(obj,reason=reason,index=index,**allowProperties)
-	if reason!=REASON_ONLYCACHE and isEditable:
+	if reason!=controlTypes.REASON_ONLYCACHE and isEditable:
 		try:
 			info=obj.makeTextInfo(textInfos.POSITION_SELECTION)
 			if not info.isCollapsed:
@@ -281,13 +271,13 @@
 			newInfo=obj.makeTextInfo(textInfos.POSITION_ALL)
 			speakTextInfo(newInfo,unit=textInfos.UNIT_PARAGRAPH,reason=reason)
 
-def speakText(text,index=None,reason=REASON_MESSAGE,symbolLevel=None):
+def speakText(text,index=None,reason=controlTypes.REASON_MESSAGE,symbolLevel=None):
 	"""Speaks some text.
 	@param text: The text to speak.
 	@type text: str
 	@param index: The index to mark this text with, which can be used later to determine whether this piece of text has been spoken.
 	@type index: int
-	@param reason: The reason for this speech; one of the REASON_* constants.
+	@param reason: The reason for this speech; one of the controlTypes.REASON_* constants.
 	@param symbolLevel: The symbol verbosity level; C{None} (default) to use the user's configuration.
 	"""
 	speechSequence=[]
@@ -425,93 +415,7 @@
 	if config.conf["keyboard"]["speakTypedCharacters"] and ord(ch)>=32:
 		speakSpelling(realChar)
 
-silentRolesOnFocus=set([
-	controlTypes.ROLE_PANE,
-	controlTypes.ROLE_ROOTPANE,
-	controlTypes.ROLE_FRAME,
-	controlTypes.ROLE_UNKNOWN,
-	controlTypes.ROLE_APPLICATION,
-	controlTypes.ROLE_TABLECELL,
-	controlTypes.ROLE_LISTITEM,
-	controlTypes.ROLE_MENUITEM,
-	controlTypes.ROLE_CHECKMENUITEM,
-	controlTypes.ROLE_TREEVIEWITEM,
-])
-
-silentValuesForRoles=set([
-	controlTypes.ROLE_CHECKBOX,
-	controlTypes.ROLE_RADIOBUTTON,
-	controlTypes.ROLE_LINK,
-	controlTypes.ROLE_MENUITEM,
-	controlTypes.ROLE_APPLICATION,
-])
-
-def processPositiveStates(role, states, reason, positiveStates):
-	positiveStates = positiveStates.copy()
-	# The user never cares about certain states.
-	if role==controlTypes.ROLE_EDITABLETEXT:
-		positiveStates.discard(controlTypes.STATE_EDITABLE)
-	if role!=controlTypes.ROLE_LINK:
-		positiveStates.discard(controlTypes.STATE_VISITED)
-	positiveStates.discard(controlTypes.STATE_SELECTABLE)
-	positiveStates.discard(controlTypes.STATE_FOCUSABLE)
-	positiveStates.discard(controlTypes.STATE_CHECKABLE)
-	if controlTypes.STATE_DRAGGING in positiveStates:
-		# It's obvious that the control is draggable if it's being dragged.
-		positiveStates.discard(controlTypes.STATE_DRAGGABLE)
-	if role == controlTypes.ROLE_COMBOBOX:
-		# Combo boxes inherently have a popup, so don't report it.
-		positiveStates.discard(controlTypes.STATE_HASPOPUP)
-	if reason == REASON_QUERY:
-		return positiveStates
-	positiveStates.discard(controlTypes.STATE_DEFUNCT)
-	positiveStates.discard(controlTypes.STATE_MODAL)
-	positiveStates.discard(controlTypes.STATE_FOCUSED)
-	positiveStates.discard(controlTypes.STATE_OFFSCREEN)
-	positiveStates.discard(controlTypes.STATE_INVISIBLE)
-	if reason != REASON_CHANGE:
-		positiveStates.discard(controlTypes.STATE_LINKED)
-		if role in (controlTypes.ROLE_LISTITEM, controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TABLEROW) and controlTypes.STATE_SELECTABLE in states:
-			positiveStates.discard(controlTypes.STATE_SELECTED)
-	if role != controlTypes.ROLE_EDITABLETEXT:
-		positiveStates.discard(controlTypes.STATE_READONLY)
-	if role == controlTypes.ROLE_CHECKBOX:
-		positiveStates.discard(controlTypes.STATE_PRESSED)
-	if role == controlTypes.ROLE_MENUITEM:
-		# The user doesn't usually care if a menu item is expanded or collapsed.
-		positiveStates.discard(controlTypes.STATE_COLLAPSED)
-		positiveStates.discard(controlTypes.STATE_EXPANDED)
-	return positiveStates
-
-def processNegativeStates(role, states, reason, negativeStates):
-	speakNegatives = set()
-	# Add the negative selected state if the control is selectable,
-	# but only if it is either focused or this is something other than a change event.
-	# The condition stops "not selected" from being spoken in some broken controls
-	# when the state change for the previous focus is issued before the focus change.
-	if role in (controlTypes.ROLE_LISTITEM, controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_TABLEROW) and controlTypes.STATE_SELECTABLE in states and (reason != REASON_CHANGE or controlTypes.STATE_FOCUSED in states):
-		speakNegatives.add(controlTypes.STATE_SELECTED)
-	# Restrict "not checked" in a similar way to "not selected".
-	if (role in (controlTypes.ROLE_CHECKBOX, controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKMENUITEM) or controlTypes.STATE_CHECKABLE in states)  and (controlTypes.STATE_HALFCHECKED not in states) and (reason != REASON_CHANGE or controlTypes.STATE_FOCUSED in states):
-		speakNegatives.add(controlTypes.STATE_CHECKED)
-	if reason == REASON_CHANGE:
-		# We want to speak this state only if it is changing to negative.
-		speakNegatives.add(controlTypes.STATE_DROPTARGET)
-		# We were given states which have changed to negative.
-		# Return only those supplied negative states which should be spoken;
-		# i.e. the states in both sets.
-		speakNegatives &= negativeStates
-		if controlTypes.STATES_SORTED & negativeStates and not controlTypes.STATES_SORTED & states:
-			# If the object has just stopped being sorted, just report not sorted.
-			# The user doesn't care how it was sorted before.
-			speakNegatives.add(controlTypes.STATE_SORTED)
-		return speakNegatives
-	else:
-		# This is not a state change; only positive states were supplied.
-		# Return all negative states which should be spoken, excluding the positive states.
-		return speakNegatives - states
-
-def speakTextInfo(info,useCache=True,formatConfig=None,unit=None,extraDetail=False,reason=REASON_QUERY,index=None):
+def speakTextInfo(info,useCache=True,formatConfig=None,unit=None,extraDetail=False,reason=controlTypes.REASON_QUERY,index=None):
 	if unit in (textInfos.UNIT_CHARACTER,textInfos.UNIT_WORD):
 		extraDetail=True
 	if not formatConfig:
@@ -651,7 +555,7 @@
 				textList.append(text)
 
 	# If there is nothing  that should cause the TextInfo to be considered non-blank, blank should be reported, unless we are doing a say all.
-	if reason != REASON_SAYALL and len(textList)==textListBlankLen:
+	if reason != controlTypes.REASON_SAYALL and len(textList)==textListBlankLen:
 		textList.append(_("blank"))
 
 	#Cache a copy of the new controlFieldStack for future use
@@ -667,12 +571,12 @@
 	if text:
 		speechSequence.append(text)
 	if speechSequence:
-		if reason==REASON_SAYALL:
+		if reason==controlTypes.REASON_SAYALL:
 			speakWithoutPauses(speechSequence)
 		else:
 			speak(speechSequence)
 
-def getSpeechTextForProperties(reason=REASON_QUERY,**propertyValues):
+def getSpeechTextForProperties(reason=controlTypes.REASON_QUERY,**propertyValues):
 	global oldTreeLevel, oldTableID, oldRowNumber, oldColumnNumber
 	textList=[]
 	name=propertyValues.get('name')
@@ -687,30 +591,30 @@
 	else:
 		speakRole=False
 		role=controlTypes.ROLE_UNKNOWN
-	value=propertyValues.get('value') if role not in silentValuesForRoles else None
+	value=propertyValues.get('value') if role not in controlTypes.ignoreValuesForRoles else None
 	rowNumber=propertyValues.get('rowNumber')
 	columnNumber=propertyValues.get('columnNumber')
 	includeTableCellCoords=propertyValues.get('includeTableCellCoords',True)
-	if speakRole and (reason not in (REASON_SAYALL,REASON_CARET,REASON_FOCUS) or not (name or value or rowNumber or columnNumber) or role not in silentRolesOnFocus):
-		textList.append(controlTypes.speechRoleLabels[role])
+	if speakRole and (reason not in (controlTypes.REASON_SAYALL, controlTypes.REASON_CARET, controlTypes.REASON_FOCUS) or not (name or value or rowNumber or columnNumber) or role not in controlTypes.ignoreRolesOnFocus):
+		textList.append(controlTypes.labels[role])
 	if value:
 		textList.append(value)
 	states=propertyValues.get('states')
 	realStates=propertyValues.get('_states',states)
 	if states is not None:
-		positiveStates=processPositiveStates(role,realStates,reason,states)
-		textList.extend([controlTypes.speechStateLabels[x] for x in positiveStates])
+		positiveStates=controlTypes.processPositiveStates(role,realStates,reason,states)
+		textList.extend([controlTypes.stateLabels[x] for x in positiveStates])
 	if 'negativeStates' in propertyValues:
 		negativeStates=propertyValues['negativeStates']
 	else:
 		negativeStates=None
-	if negativeStates is not None or (reason != REASON_CHANGE and states is not None):
-		negativeStates=processNegativeStates(role, realStates, reason, negativeStates)
+	if negativeStates is not None or (reason != controlTypes.REASON_CHANGE and states is not None):
+		negativeStates=controlTypes.processNegativeStates(role, realStates, reason, negativeStates)
 		if controlTypes.STATE_DROPTARGET in negativeStates:
 			# "not drop target" doesn't make any sense, so use a custom message.
 			textList.append(_("done dragging"))
 			negativeStates.discard(controlTypes.STATE_DROPTARGET)
-		textList.extend([_("not %s")%controlTypes.speechStateLabels[x] for x in negativeStates])
+		textList.extend([_("not %s")%controlTypes.stateLabels[x] for x in negativeStates])
 	if 'description' in propertyValues:
 		textList.append(propertyValues['description'])
 	if 'keyboardShortcut' in propertyValues:
@@ -722,7 +626,7 @@
 	if 'positionInfo_level' in propertyValues:
 		level=propertyValues.get('positionInfo_level',None)
 		role=propertyValues.get('role',None)
-		if level is not None and role in (controlTypes.ROLE_TREEVIEWITEM,controlTypes.ROLE_LISTITEM) and level!=oldTreeLevel:
+		if level is not None and role in (controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_LISTITEM) and level!=oldTreeLevel:
 			textList.insert(0,_("level %s")%level)
 			oldTreeLevel=level
 		elif level:
@@ -766,21 +670,21 @@
 		formatConfig=config.conf["documentFormatting"]
 
 	childCount=int(attrs.get('_childcount',"0"))
-	if reason==REASON_FOCUS or attrs.get('alwaysReportName',False):
+	if reason==controlTypes.REASON_FOCUS or attrs.get('alwaysReportName',False):
 		name=attrs.get('name',"")
 	else:
 		name=""
-	role=attrs.get('role',controlTypes.ROLE_UNKNOWN)
+	role=attrs.get('role', controlTypes.ROLE_UNKNOWN)
 	states=attrs.get('states',set())
 	keyboardShortcut=attrs.get('keyboardShortcut', "")
-	if reason==REASON_FOCUS or attrs.get('alwaysReportDescription',False):
+	if reason==controlTypes.REASON_FOCUS or attrs.get('alwaysReportDescription',False):
 		description=attrs.get('description',"")
 	else:
 		description=""
 	level=attrs.get('level',None)
 
 	#Remove the clickable state from controls that are clearly clickable according to their role
-	if role in (controlTypes.ROLE_LINK,controlTypes.ROLE_BUTTON,controlTypes.ROLE_CHECKBOX,controlTypes.ROLE_RADIOBUTTON):
+	if role in (controlTypes.ROLE_LINK, controlTypes.ROLE_BUTTON, controlTypes.ROLE_CHECKBOX, controlTypes.ROLE_RADIOBUTTON):
 		states=states.copy()
 		states.discard(controlTypes.STATE_CLICKABLE)
 
@@ -806,12 +710,12 @@
 		tableID=None
 
 	# Honour verbosity configuration.
-	if reason in (REASON_CARET,REASON_SAYALL,REASON_FOCUS) and (
+	if reason in (controlTypes.REASON_CARET, controlTypes.REASON_SAYALL, controlTypes.REASON_FOCUS) and (
 		(role==controlTypes.ROLE_LINK and not formatConfig["reportLinks"]) or 
 		(role==controlTypes.ROLE_HEADING and not formatConfig["reportHeadings"]) or
 		(role==controlTypes.ROLE_BLOCKQUOTE and not formatConfig["reportBlockQuotes"]) or
-		(role in (controlTypes.ROLE_TABLE,controlTypes.ROLE_TABLECELL,controlTypes.ROLE_TABLEROWHEADER,controlTypes.ROLE_TABLECOLUMNHEADER) and not formatConfig["reportTables"]) or
-		(role in (controlTypes.ROLE_LIST,controlTypes.ROLE_LISTITEM) and controlTypes.STATE_READONLY in states and not formatConfig["reportLists"])
+		(role in (controlTypes.ROLE_TABLE, controlTypes.ROLE_TABLECELL, controlTypes.ROLE_TABLEROWHEADER, controlTypes.ROLE_TABLECOLUMNHEADER) and not formatConfig["reportTables"]) or
+		(role in (controlTypes.ROLE_LIST, controlTypes.ROLE_LISTITEM) and controlTypes.STATE_READONLY in states and not formatConfig["reportLists"])
 	):
 		return ""
 
@@ -830,7 +734,7 @@
 	# speakExitForOther: When moving by word or character, speak when the user exits the control.
 	speakEntry=speakWithinForLine=speakExitForLine=speakExitForOther=False
 	if (
-		role in (controlTypes.ROLE_LINK,controlTypes.ROLE_HEADING,controlTypes.ROLE_BUTTON,controlTypes.ROLE_RADIOBUTTON,controlTypes.ROLE_CHECKBOX,controlTypes.ROLE_GRAPHIC,controlTypes.ROLE_MENUITEM,controlTypes.ROLE_TAB,controlTypes.ROLE_COMBOBOX,controlTypes.ROLE_SLIDER,controlTypes.ROLE_SPINBUTTON,controlTypes.ROLE_COMBOBOX,controlTypes.ROLE_PROGRESSBAR)
+		role in (controlTypes.ROLE_LINK, controlTypes.ROLE_HEADING, controlTypes.ROLE_BUTTON, controlTypes.ROLE_RADIOBUTTON, controlTypes.ROLE_CHECKBOX, controlTypes.ROLE_GRAPHIC, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TAB, controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_SLIDER, controlTypes.ROLE_SPINBUTTON, controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_PROGRESSBAR)
 		or (role==controlTypes.ROLE_EDITABLETEXT and controlTypes.STATE_MULTILINE not in states and (controlTypes.STATE_READONLY not in states or controlTypes.STATE_FOCUSABLE in states))
 		or (role==controlTypes.ROLE_LIST and controlTypes.STATE_READONLY not in states)
 	):
@@ -838,11 +742,11 @@
 		speakEntry=True
 		speakWithinForLine=True
 		speakExitForOther=True
-	elif role in (controlTypes.ROLE_SEPARATOR,controlTypes.ROLE_EMBEDDEDOBJECT):
+	elif role in (controlTypes.ROLE_SEPARATOR, controlTypes.ROLE_EMBEDDEDOBJECT):
 		# This node is only ever a marker; i.e. single character.
 		speakEntry=True
 	elif (
-		role in (controlTypes.ROLE_BLOCKQUOTE,controlTypes.ROLE_FRAME,controlTypes.ROLE_INTERNALFRAME,controlTypes.ROLE_TOOLBAR,controlTypes.ROLE_MENUBAR,controlTypes.ROLE_POPUPMENU)
+		role in (controlTypes.ROLE_BLOCKQUOTE, controlTypes.ROLE_FRAME, controlTypes.ROLE_INTERNALFRAME, controlTypes.ROLE_TOOLBAR, controlTypes.ROLE_MENUBAR, controlTypes.ROLE_POPUPMENU)
 		or (role==controlTypes.ROLE_EDITABLETEXT and (controlTypes.STATE_READONLY not in states or controlTypes.STATE_FOCUSABLE in states) and controlTypes.STATE_MULTILINE in states)
 		or (role==controlTypes.ROLE_LIST and controlTypes.STATE_READONLY in states)
 		or (role==controlTypes.ROLE_DOCUMENT and controlTypes.STATE_EDITABLE in states)
@@ -855,7 +759,7 @@
 
 	# Determine the order of speech.
 	# speakContentFirst: Speak the content before the control field info.
-	speakContentFirst=reason==REASON_FOCUS and role not in (controlTypes.ROLE_EDITABLETEXT,controlTypes.ROLE_COMBOBOX) and controlTypes.STATE_EDITABLE not in states
+	speakContentFirst=reason==controlTypes.REASON_FOCUS and role not in (controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_COMBOBOX) and controlTypes.STATE_EDITABLE not in states
 	# speakStatesFirst: Speak the states before the role.
 	speakStatesFirst=role==controlTypes.ROLE_LINK
 
@@ -871,7 +775,7 @@
 	elif fieldType=="start_addedToControlFieldStack" and role==controlTypes.ROLE_TABLE and tableID:
 		# Table.
 		return " ".join((roleText, getSpeechTextForProperties(_tableID=tableID, rowCount=attrs.get("table-rowcount"), columnCount=attrs.get("table-columncount"))))
-	elif fieldType=="start_addedToControlFieldStack" and role in (controlTypes.ROLE_TABLECELL,controlTypes.ROLE_TABLECOLUMNHEADER,controlTypes.ROLE_TABLEROWHEADER) and tableID:
+	elif fieldType=="start_addedToControlFieldStack" and role in (controlTypes.ROLE_TABLECELL, controlTypes.ROLE_TABLECOLUMNHEADER, controlTypes.ROLE_TABLEROWHEADER) and tableID:
 		# Table cell.
 		reportTableHeaders = formatConfig["reportTableHeaders"]
 		reportTableCellCoords = formatConfig["reportTableCellCoords"]

=== modified file 'source/virtualBuffers/__init__.py'
--- source/virtualBuffers/__init__.py	2011-06-08 03:39:10 +0000
+++ source/virtualBuffers/__init__.py	2011-06-17 11:59:40 +0000
@@ -1,3 +1,9 @@
+#VirtualBuffer.py
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
 import time
 import threading
 import ctypes
@@ -488,7 +494,7 @@
 
 	def _reportElement(self, element):
 		speech.cancelSpeech()
-		speech.speakTextInfo(element,reason=speech.REASON_FOCUS)
+		speech.speakTextInfo(element,reason=controlTypes.REASON_FOCUS)
 
 class VirtualBuffer(cursorManager.CursorManager, treeInterceptorHandler.TreeInterceptor):
 
@@ -647,7 +653,7 @@
 					self.selection = self.makeTextInfo(initialPos)
 				speech.cancelSpeech()
 				reportPassThrough(self)
-				speech.speakObjectProperties(self.rootNVDAObject,name=True,states=True,reason=speech.REASON_FOCUS)
+				speech.speakObjectProperties(self.rootNVDAObject,name=True,states=True,reason=controlTypes.REASON_FOCUS)
 				info=self.makeTextInfo(textInfos.POSITION_CARET)
 				sayAllHandler.readText(info,sayAllHandler.CURSOR_CARET)
 			self._hadFirstGainFocus = True
@@ -656,13 +662,13 @@
 			# This buffer has had focus before.
 			if not self.passThrough:
 				# Speak it like we would speak focus on any other document object.
-				speech.speakObject(self.rootNVDAObject, reason=speech.REASON_FOCUS)
+				speech.speakObject(self.rootNVDAObject, reason=controlTypes.REASON_FOCUS)
 				info = self.selection
 				if not info.isCollapsed:
 					speech.speakSelectionMessage(_("selected %s"), info.text)
 				else:
 					info.expand(textInfos.UNIT_LINE)
-					speech.speakTextInfo(info, reason=speech.REASON_CARET)
+					speech.speakTextInfo(info, reason=controlTypes.REASON_CARET)
 
 		reportPassThrough(self)
 		braille.handler.handleGainFocus(self)
@@ -692,17 +698,17 @@
 			reportPassThrough(self)
 		elif obj.role == controlTypes.ROLE_EMBEDDEDOBJECT:
 			obj.setFocus()
-			speech.speakObject(obj, reason=speech.REASON_FOCUS)
+			speech.speakObject(obj, reason=controlTypes.REASON_FOCUS)
 		else:
 			self._activateNVDAObject(obj)
 
-	def _set_selection(self, info, reason=speech.REASON_CARET):
+	def _set_selection(self, info, reason=controlTypes.REASON_CARET):
 		super(VirtualBuffer, self)._set_selection(info)
 		if isScriptWaiting() or not info.isCollapsed:
 			return
 		if config.conf['reviewCursor']['followCaret'] and api.getNavigatorObject() is self.rootNVDAObject:
 			api.setReviewPosition(info)
-		if reason == speech.REASON_FOCUS:
+		if reason == controlTypes.REASON_FOCUS:
 			focusObj = api.getFocusObject()
 			if focusObj==self.rootNVDAObject:
 				return
@@ -800,7 +806,7 @@
 			if info.compareEndPoints(fieldInfo, "endToEnd") > 0:
 				# We've expanded past the end of the field, so limit to the end of the field.
 				info.setEndPoint(fieldInfo, "endToEnd")
-		speech.speakTextInfo(info, reason=speech.REASON_FOCUS)
+		speech.speakTextInfo(info, reason=controlTypes.REASON_FOCUS)
 		info.collapse()
 		self._set_selection(info, reason=self.REASON_QUICKNAV)
 
@@ -837,13 +843,13 @@
 		"""Determine whether pass through mode should be enabled or disabled for a given object.
 		@param obj: The object in question.
 		@type obj: L{NVDAObjects.NVDAObject}
-		@param reason: The reason for this query; one of the speech reasons, L{REASON_QUICKNAV}, or C{None} for manual pass through mode activation by the user.
+		@param reason: The reason for this query; one of the reasons in controlTypes, L{REASON_QUICKNAV}, or C{None} for manual pass through mode activation by the user.
 		@return: C{True} if pass through mode should be enabled, C{False} if it should be disabled.
 		"""
 		if reason and (
 			self.disableAutoPassThrough
-			or (reason == speech.REASON_FOCUS and not config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"])
-			or (reason == speech.REASON_CARET and not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"])
+			or (reason == controlTypes.REASON_FOCUS and not config.conf["virtualBuffers"]["autoPassThroughOnFocusChange"])
+			or (reason == controlTypes.REASON_CARET and not config.conf["virtualBuffers"]["autoPassThroughOnCaretMove"])
 		):
 			# This check relates to auto pass through and auto pass through is disabled, so don't change the pass through state.
 			return self.passThrough
@@ -855,9 +861,9 @@
 		role = obj.role
 		if controlTypes.STATE_READONLY in states and role != controlTypes.ROLE_EDITABLETEXT:
 			return False
-		if reason == speech.REASON_CARET:
+		if reason == controlTypes.REASON_CARET:
 			return role == controlTypes.ROLE_EDITABLETEXT or (role == controlTypes.ROLE_DOCUMENT and controlTypes.STATE_EDITABLE in states)
-		if reason == speech.REASON_FOCUS and role in (controlTypes.ROLE_LISTITEM, controlTypes.ROLE_RADIOBUTTON):
+		if reason == controlTypes.REASON_FOCUS and role in (controlTypes.ROLE_LISTITEM, controlTypes.ROLE_RADIOBUTTON):
 			return True
 		if role in (controlTypes.ROLE_COMBOBOX, controlTypes.ROLE_EDITABLETEXT, controlTypes.ROLE_LIST, controlTypes.ROLE_SLIDER, controlTypes.ROLE_TABCONTROL, controlTypes.ROLE_TAB, controlTypes.ROLE_MENUBAR, controlTypes.ROLE_POPUPMENU, controlTypes.ROLE_MENUITEM, controlTypes.ROLE_TREEVIEW, controlTypes.ROLE_TREEVIEWITEM, controlTypes.ROLE_SPINBUTTON) or controlTypes.STATE_EDITABLE in states:
 			return True
@@ -942,11 +948,11 @@
 			# This node is already focused, so we need to move to and speak this node here.
 			newCaret = newInfo.copy()
 			newCaret.collapse()
-			self._set_selection(newCaret,reason=speech.REASON_FOCUS)
+			self._set_selection(newCaret,reason=controlTypes.REASON_FOCUS)
 			if self.passThrough:
 				obj.event_gainFocus()
 			else:
-				speech.speakTextInfo(newInfo,reason=speech.REASON_FOCUS)
+				speech.speakTextInfo(newInfo,reason=controlTypes.REASON_FOCUS)
 		else:
 			# This node doesn't have the focus, so just set focus to it. The gainFocus event will handle the rest.
 			obj.setFocus()
@@ -1008,7 +1014,7 @@
 		except:
 			# This object is not in the virtual buffer, even though it resides beneath the document.
 			# Automatic pass through should be enabled in certain circumstances where this occurs.
-			if not self.passThrough and self.shouldPassThrough(obj,reason=speech.REASON_FOCUS):
+			if not self.passThrough and self.shouldPassThrough(obj,reason=controlTypes.REASON_FOCUS):
 				self.passThrough=True
 				reportPassThrough(self)
 				self._replayFocusEnteredEvents()
@@ -1025,24 +1031,24 @@
 				# If pass-through is disabled, cancel speech, as a focus change should cause page reading to stop.
 				# This must be done before auto-pass-through occurs, as we want to stop page reading even if pass-through will be automatically enabled by this focus change.
 				speech.cancelSpeech()
-			self.passThrough=self.shouldPassThrough(obj,reason=speech.REASON_FOCUS)
+			self.passThrough=self.shouldPassThrough(obj,reason=controlTypes.REASON_FOCUS)
 			if not self.passThrough:
 				# We read the info from the buffer instead of the control itself.
-				speech.speakTextInfo(focusInfo,reason=speech.REASON_FOCUS)
+				speech.speakTextInfo(focusInfo,reason=controlTypes.REASON_FOCUS)
 				# However, we still want to update the speech property cache so that property changes will be spoken properly.
-				speech.speakObject(obj,speech.REASON_ONLYCACHE)
+				speech.speakObject(obj,controlTypes.REASON_ONLYCACHE)
 			else:
 				if not oldPassThrough:
 					self._replayFocusEnteredEvents()
 				nextHandler()
 			focusInfo.collapse()
-			self._set_selection(focusInfo,reason=speech.REASON_FOCUS)
+			self._set_selection(focusInfo,reason=controlTypes.REASON_FOCUS)
 		else:
 			# The virtual buffer caret was already at the focused node.
 			if not self.passThrough:
 				# This focus change was caused by a virtual caret movement, so don't speak the focused node to avoid double speaking.
 				# However, we still want to update the speech property cache so that property changes will be spoken properly.
-				speech.speakObject(obj,speech.REASON_ONLYCACHE)
+				speech.speakObject(obj,controlTypes.REASON_ONLYCACHE)
 			else:
 				return nextHandler()
 
@@ -1076,7 +1082,7 @@
 		if not scrollInfo.isOverlapping(caretInfo):
 			if scrollInfo.isCollapsed:
 				scrollInfo.expand(textInfos.UNIT_LINE)
-			speech.speakTextInfo(scrollInfo,reason=speech.REASON_CARET)
+			speech.speakTextInfo(scrollInfo,reason=controlTypes.REASON_CARET)
 			scrollInfo.collapse()
 			self.selection = scrollInfo
 			return True
@@ -1192,7 +1198,7 @@
 			# Retrieve the cell on which we started.
 			info = next(self._iterTableCells(tableID, row=origRow, column=origCol))
 
-		speech.speakTextInfo(info,formatConfig=formatConfig,reason=speech.REASON_CARET)
+		speech.speakTextInfo(info,formatConfig=formatConfig,reason=controlTypes.REASON_CARET)
 		info.collapse()
 		self.selection = info
 

# Begin bundle
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
