From ab310b1165643461ca5a1d0a96e71e378403dbd2 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 19 Oct 2022 14:08:53 +0000 Subject: [PATCH] fpspreadsheet: Fix writing of defective UTF8 strings to xlsx. Related to issue #39045. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8569 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../source/common/fpsxmlcommon.pas | 35 +++++++++---------- .../fpspreadsheet/source/common/xlsxooxml.pas | 5 ++- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/components/fpspreadsheet/source/common/fpsxmlcommon.pas b/components/fpspreadsheet/source/common/fpsxmlcommon.pas index cbe41b132..8e266c27b 100644 --- a/components/fpspreadsheet/source/common/fpsxmlcommon.pas +++ b/components/fpspreadsheet/source/common/fpsxmlcommon.pas @@ -62,6 +62,7 @@ procedure DestroyTempStream(AStream: TStream); implementation uses + LazUTF8, (* {$IF FPC_FULLVERSION >= 20701} zipper, @@ -162,7 +163,7 @@ begin (Pos(''', AppoSt) = 1) or (Pos('%', AppoSt) = 1) // % then begin - //'&' is the first char of a special chat, it must not be converted + //'&' is the first char of a special char, it must not be converted Result := Result + AText[Idx]; end else begin Result := Result + '&'; @@ -174,21 +175,13 @@ begin '''':Result := Result + '''; '%': Result := Result + '%'; #10: if ProcessLineEndings then - Result := Result + ' ' else + Result := Result + ' ' + else Result := Result + #10; #13: if ProcessLineEndings then - Result := Result + ' ' else + Result := Result + ' ' + else Result := Result + #13; - { this breaks multi-line labels in xlsx - #10: begin - Result := Result + '
'; - if (idx < Length(AText)) and (AText[idx+1] = #13) then inc(idx); - end; - #13: begin - Result := Result + '
'; - if (idx < Length(AText)) and (AText[idx+1] = #10) then inc(idx); - end; - } else Result := Result + AText[Idx]; end; @@ -218,15 +211,21 @@ const BOX = #$E2#$8E#$95; var i: Integer; + P: PChar; begin Result := true; - for i := Length(AText) downto 1 do - if (AText[i] < #32) and not (AText[i] in [#9, #10, #13]) then begin - // Replace invalid character by box symbol - Delete(AText, i, 1); - Insert(BOX, AText, i); + + repeat + P := PChar(AText); + i := FindInvalidUTF8CodePoint(P, Length(AText), true); + if i >= 0 then + begin + Delete(AText, i+1, 1); + Insert(BOX, AText, i+1); Result := false; end; + until (i < 0); + if ReplaceSpecialChars then AText := UTF8TextToXMLText(AText, ProcessLineEndings); end; diff --git a/components/fpspreadsheet/source/common/xlsxooxml.pas b/components/fpspreadsheet/source/common/xlsxooxml.pas index 70e14b163..43f4736c1 100644 --- a/components/fpspreadsheet/source/common/xlsxooxml.pas +++ b/components/fpspreadsheet/source/common/xlsxooxml.pas @@ -7947,8 +7947,7 @@ begin ResultingValue := AValue; { Check for invalid characters } - txt := ResultingValue; - if not ValidXMLText(txt) then + if not ValidXMLText(ResultingValue) then Workbook.AddErrorMsg( rsInvalidCharacterInCell, [ GetCellString(ARow, ACol) @@ -7959,7 +7958,7 @@ begin // unformatted string AppendToStream(FSSharedStrings, '' + - '' + txt + '' + + '' + ResultingValue + '' + '') else begin