# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: mhameed@src.gnome.org-20110617124746-cufp3o7kxf13vd8x
# target_branch: http://bzr.nvaccess.org/nvda/main/
# testament_sha1: d29a9fb6a717ed03c0d9e3a57324676dd7020200
# timestamp: 2011-06-18 08:38:17 +0100
# base_revision_id: mick@kulgan.net-20110618071115-cezi1vx8u8na23rs
# 
# 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 12:47:46 +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"),
@@ -209,22 +209,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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

