Repository: nvaccess/nvda

Issue:
Word with UIA enabled: Spelling error announced at start of line.
Initial report by @bramd

### Steps to reproduce:
1. Open Word with UIA enabled.
2. Type the following line: `This is a spellling error.`
3. Press enter.
4. Press up arrow.

### Actual behavior:
NVDA says: `[spelling error] This is a spellling error.`

### Expected behavior:
NVDA says: `This is a [spelling error] spellling error.`

### System configuration:

#### NVDA Installed

#### NVDA version:
alpha-15781

#### Windows version:
1803 (17134.191)

#### Name and version of other software in use when reproducing the issue:
MS Word 16.0.10325.20082

### Other questions:

#### Does the issue still occur after restarting your PC?
Yes

#### Have you tried any other versions of NVDA?
No



Discussion:
Oopps. I broke this in the recent braille fixes.

getTextWithFields_text is overridden twice in WordDocumentTextInfo.

I'll address this in a new PR.



Resolving patch:
diff --git a/source/NVDAObjects/UIA/__init__.py b/source/NVDAObjects/UIA/__init__.py
--- a/source/NVDAObjects/UIA/__init__.py
+++ b/source/NVDAObjects/UIA/__init__.py
@@ -423,15 +423,13 @@ def _getTextFromUIARange(self,range):
 		"""
 		return range.getText(-1)
 
-	def _getTextWithFields_text(self,textRange,formatConfig,ignoreEmptyChunks=True,UIAFormatUnits=None):
+	def _getTextWithFields_text(self,textRange,formatConfig,UIAFormatUnits=None):
 		"""
 		Yields format fields and text for the given UI Automation text range, split up by the first available UI Automation text unit that does not result in mixed attribute values.
 		@param textRange: the UI Automation text range to walk.
 		@type textRange: L{UIAHandler.IUIAutomationTextRange}
 		@param formatConfig: the types of formatting requested.
 		@ type formatConfig: a dictionary of NVDA document formatting configuration keys with values set to true for those types that should be fetched.
-		@param ignoreEmptyChunks: if true, textRanges where the text is empty will not be emitted nor the formatField directly before it. 
-		@param ignoreEmptyChunks: bool
 		@param UIAFormatUnits: the UI Automation text units (in order of resolution) that should be used to split the text so as to avoid mixed attribute values. This is None by default.
 			If the parameter is a list of 1 or more units, The range will be split by the first unit in the list, and this method will be recursively run on each subrange, with the remaining units in this list given as the value of this parameter. 
 			If this parameter is an empty list, then formatting and text is fetched for the entire range, but any mixed attribute values are ignored and no splitting occures.
@@ -452,7 +450,7 @@ def _getTextWithFields_text(self,textRange,formatConfig,ignoreEmptyChunks=True,U
 		rangeIter=iterUIARangeByUnit(textRange,unit) if unit is not None else [textRange]
 		for tempRange in rangeIter:
 			text=self._getTextFromUIARange(tempRange) or ""
-			if not ignoreEmptyChunks or text:
+			if text:
 				log.debug("Chunk has text. Fetching formatting")
 				try:
 					field=self._getFormatFieldAtRange(tempRange,formatConfig,ignoreMixedValues=len(furtherUIAFormatUnits)==0)
diff --git a/source/NVDAObjects/UIA/wordDocument.py b/source/NVDAObjects/UIA/wordDocument.py
--- a/source/NVDAObjects/UIA/wordDocument.py
+++ b/source/NVDAObjects/UIA/wordDocument.py
@@ -161,11 +161,6 @@ def expand(self,unit):
 				docInfo=self.obj.makeTextInfo(textInfos.POSITION_ALL)
 				self.setEndPoint(docInfo,"endToEnd")
 
-	def _getTextWithFields_text(self,textRange,formatConfig,ignoreEmptyChunks=False,UIAFormatUnits=None):
-		# This override just changes ignoreEmptyChunks to false by default.
-		# We need this so that graphics and other embeded objects in MS Word get exposed.
-		return super(WordDocumentTextInfo,self)._getTextWithFields_text(textRange,formatConfig,ignoreEmptyChunks,UIAFormatUnits)
-
 	def _get_isCollapsed(self):
 		res=super(WordDocumentTextInfo,self).isCollapsed
 		if res: 
@@ -182,6 +177,18 @@ def getTextWithFields(self,formatConfig=None):
 		if len(fields)==0: 
 			# Nothing to do... was probably a collapsed range.
 			return fields
+		# Sometimes embedded objects and graphics In MS Word can cause a controlStart then a controlEnd with no actual formatChange / text in the middle.
+		# SpeakTextInfo always expects that the first lot of controlStarts will always contain some text.
+		# Therefore ensure that the first lot of controlStarts does contain some text by inserting a blank formatChange and empty string in this case.
+		for index in xrange(len(fields)):
+			field=fields[index]
+			if isinstance(field,textInfos.FieldCommand) and field.command=="controlStart":
+				continue
+			elif isinstance(field,textInfos.FieldCommand) and field.command=="controlEnd":
+				formatChange=textInfos.FieldCommand("formatChange",textInfos.FormatField())
+				fields.insert(index,formatChange)
+				fields.insert(index+1,"")
+			break
 		##7971: Microsoft Word exposes list bullets as part of the actual text.
 		# This then confuses NVDA's braille cursor routing as it expects that there is a one-to-one mapping between characters in the text string and   unit character moves.
 		# Therefore, detect when at the start of a list, and strip the bullet from the text string, placing it in the text's formatField as line-prefix.


Test patch: