Repository: nvaccess/nvda

Issue:
NVDA freeze when copying large amount of text

### Steps to reproduce:

* go to Wikipedia's [World War I](https://en.wikipedia.org/wiki/World_War_I) page
* press ctrl+A to select all
* press ctrl+C to copy
* Alt+Tab to another application

### Actual behavior:

NVDA freezes during a lot of time (maybe 30 seconds)

### Expected behavior:
Text should be copied without NVDA freezing.

### Note
Issue most likely due to the merge of PR #9843.
A solution could be to report the copied text only if its length is less than a specific value, and to report the number of copied characters else. This is the strategy used by the selection reporting.


### System configuration
#### NVDA installed/portable/running from source:
Temporary copy (installer) and portable version.
#### NVDA version:
Today's alpha:
Version : alpha-21371,376edfcf

#### Windows version:
Windows 10 1809 (64-bit) build 17763.1518
#### Name and version of other software in use when reproducing the issue:
Chrome - Version 85.0.4183.121 (Build officiel) (64 bits)

#### Other information about your system:

### Other questions
#### Does the issue still occur after restarting your computer?
Not tested.

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
NVDA 2020.3 is OK.

#### If addons are disabled, is your problem still occuring?
Yes

#### Did you try to run the COM registry fixing tool in NVDA menu / tools?
No



Discussion:
Cc @JulienCochuyt 
@CyrilleB79 
Sorry for missing this issue while testing.
My primary speech synth is eSpeak, which does not exhibit the issue. I've thought Speech Refactor was the cause for the success.
Now testing with OneCore proves me wrong.
You're proposed solution of aligning to the behavior of selection announcement / clipboard announcement sound reasonable to me.
I'll try to quickly work it out this afternoon.
`speech._getSelectionMessageSpeech` limits to 512 characters and simply reports "%d characters"
`globalCommands.script_reportClipboardText` limits to 1024 characters and reports "The clipboard contains a large portion of text. It is %s characters long"

I'd rather go the middle way: Limit to 1024 and simply report "%d characters copied to clipboard".
An alternative approach could be to also report portions of the beginning and end of the lengthy text, ie. "%d characters copied to clipboard, starting with {snippet}, ending with {snippet}".
What do you think?
> `speech._getSelectionMessageSpeech` limits to 512 characters and simply reports "%d characters"
> `globalCommands.script_reportClipboardText` limits to 1024 characters and reports "The clipboard contains a large portion of text. It is %s characters long"
> 
> I'd rather go the middle way: Limit to 1024 and simply report "%d characters copied to clipboard".

I agree with this solution.

> An alternative approach could be to also report portions of the beginning and end of the lengthy text, ie. "%d characters copied to clipboard, starting with {snippet}, ending with {snippet}".
> What do you think?

For now, I would suggest to limit to your first proposal to be more or less aligned with `speech._getSelectionMessageSpeech` and `globalCommands.script_reportClipboard` in order to fix the initial PR #9843.

Announcing the beginning and the end of the copied text could be done in a second time. I think there is a discussion about this regarding selection. If I find the issue again, I will add the reference here.



Resolving patch:
diff --git a/source/ui.py b/source/ui.py
--- a/source/ui.py
+++ b/source/ui.py
@@ -106,10 +106,16 @@ def reportTextCopiedToClipboard(text: Optional[str] = None):
 		# or the clipboard content did not match what was just copied.
 		message(_("Unable to copy"))
 		return
+	# Depending on the speech synthesizer, large amount of spoken text can freeze NVDA (#11843)
+	if len(text) < 1024:
+		spokenText = text
+	else:
+		# Translators: Spoken instead of a lengthy text when copied to clipboard.
+		spokenText = _("%d characters") % len(text)
 	message(
 		# Translators: Announced when a text has been copied to clipboard.
 		# {text} is replaced by the copied text.
-		text=_("Copied to clipboard: {text}").format(text=text),
+		text=_("Copied to clipboard: {text}").format(text=spokenText),
 		# Translators: Displayed in braille when a text has been copied to clipboard.
 		# {text} is replaced by the copied text.
 		brailleText=_("Copied: {text}").format(text=text)


Test patch: