Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions Src/views/VwSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5417,6 +5417,72 @@ bool CheckForParaBreak(const wchar * pchw, int ich, int cch, int * pichNext)
return false;
}

/// <summary>
/// Check if the selected text (the paste target) is a complete single paragraph.
/// </summary>
/// <returns>
/// True: If the selection contains exactly one complete paragraph, which means that the selection starts
/// at the beginning of a paragraph and ends at the end of the same paragraph.
/// False: If the selection contains text from more than one paragraph or only contains part of a paragraph.
/// </returns>
bool VwTextSelection::SelectedTextIsSingleParagraph()
{
VwParagraphBox* notUsed;
int targetMin;
int targetLim; // One past the last selected character, relative to the last paragraph.
GetFirstAndLast(&notUsed, &notUsed, &targetMin, &targetLim);

if (!m_pvpboxEnd &&
targetMin == 0 &&
m_pvpbox->Source()->CStrings() == 1)
{
ITsString* firstStr = NULL;
m_pvpbox->Source()->StringAtIndex(0, &firstStr);
int firstStrLen = 0;
CheckHr(firstStr->get_Length(&firstStrLen));

if (targetLim == firstStrLen)
Comment on lines +5435 to +5444
{
return true;
}
}
return false;
}

/// <summary>
/// Check if the replacement text is a single paragraph.
/// </summary>
/// <param name="replacementTstr">The replacement text.</param>
/// <returns>
/// True: If the replacement text contains exactly one paragraph, which means that the text ends with
/// a '\n' and contains no other '\n' characters.
/// False: If the replacement text contains more than one '\n' or if the '\n' is not at the end.
/// </returns>
bool VwTextSelection::ReplacementTextIsSingleParagraph(ITsString* replacementTstr)
{
int replacementCharCount;
SmartBstr replacementBstr;
CheckHr(replacementTstr->get_Length(&replacementCharCount));
CheckHr(replacementTstr->get_Text(&replacementBstr));
const wchar* replacementText = replacementBstr.Chars();
for (int ii = 0; ii < replacementCharCount; ii++)
{
if (replacementText[ii] == '\n')
{
// The last character is a '\n' and there are no other '\n' characters in the string.
if (ii == replacementCharCount - 1)
{
return true;
}
else
{
break;
}
}
}
return false;
Comment on lines +5466 to +5483
}

/*----------------------------------------------------------------------------------------------
Replace what is selected with a TsString.
If the string contains newlines, the properties associated with the Newline become
Expand Down Expand Up @@ -5449,6 +5515,21 @@ STDMETHODIMP VwTextSelection::ReplaceWithTsString(ITsString * ptss)
CheckHr(ptss->get_NormalizedForm(knmNFD, &qtssNorm));
ptss = qtssNorm;

// If the selected text (the paste target) is a complete single paragraph, and the replacement
// text is a complete single paragraph (has exactly one terminal paragraph marker with no interior
// paragraph breaks) then trim that marker so that we do character replacement instead of paragraph
// replacement. Paragraph replacement fails in this case: LT-20857 (and many others).
if (SelectedTextIsSingleParagraph() && ReplacementTextIsSingleParagraph(ptss))
{
int replacementCharCount;
CheckHr(ptss->get_Length(&replacementCharCount));

// Remove the trailing '\n'.
ITsStringPtr trimmedReplacementText;
MakeSubString(ptss, 0, replacementCharCount - 1, &trimmedReplacementText);
ptss = trimmedReplacementText;
}

// default: only position changed; set to 2 if para changes
VwSelChangeType nHowChanged = ksctSamePara;
try
Expand Down
2 changes: 2 additions & 0 deletions Src/views/VwSelection.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,8 @@ class VwTextSelection : public VwSelection
IVwViewConstructor * pvvcEdit, int fragEdit, ITsStrBldr * ptsb, bool * pfOk);
virtual bool RuinedByDeleting(VwBox * pbox, VwBox * pboxReplacement=0);
void MakeSubString(ITsString * ptss, int ichMin, int ichLim, ITsString ** pptssSub);
bool SelectedTextIsSingleParagraph();
bool ReplacementTextIsSingleParagraph(ITsString* ptss);

void SetInsertionProps(ITsTextProps * pttp)
{
Expand Down
Loading