diff --git a/components/fpspreadsheet/fpshtml.pas b/components/fpspreadsheet/fpshtml.pas index 1c931c49d..44137b625 100644 --- a/components/fpspreadsheet/fpshtml.pas +++ b/components/fpspreadsheet/fpshtml.pas @@ -921,38 +921,16 @@ begin end; procedure TsHTMLReader.TextFoundHandler(AText: String); -// Todo: find correct way to retain spaces -// Example: -// 123abc is rendered by browser as 123abc (with abc bold) -// 123 -// abc is rendered as 123 abc -// The current way is not good. -var - beginsWithLineEnding, endsWithLineEnding: Boolean; begin if FInCell then begin - beginsWithLineEnding := (AText <> '') and (AText[1] in [#13, #10]); - endsWithLineEnding := (AText <> '') and (AText[Length(AText)] in [#13,#10]); AText := CleanHTMLString(ConvertEncoding(AText, FEncoding, EncodingUTF8)); if AText <> '' then begin if FCellText = '' then FCellText := AText - else - if beginsWithLineEnding then - FCellText := FCellText + ' ' + AText - else - if endsWithLineEnding then - FCelLText := FCelLText + AText + ' ' else FCellText := FCellText + AText; - { - if FCellText[Length(FCellText)] = #10 then - FCellText := FCellText + AText - else - FCellText := FCellText + ' ' + AText; - } end; end; end; diff --git a/components/fpspreadsheet/fpshtmlutils.pas b/components/fpspreadsheet/fpshtmlutils.pas index 026591b66..ff3ce3c82 100644 --- a/components/fpspreadsheet/fpshtmlutils.pas +++ b/components/fpspreadsheet/fpshtmlutils.pas @@ -376,28 +376,46 @@ end; function CleanHTMLString(AText: String): String; var - len: Integer; ent: TsHTMLEntity; P: PChar; ch: Char; + hasStartSpace, hasEndSpace: Boolean; begin Result := ''; // Remove leading and trailing spaces and line endings coming from formatted - // source lines - while (Length(AText) > 0) and (AText[1] in [#9, #10, #13, ' ']) do - Delete(AText, 1,1); + // source lines. Retain 1 single space, at the end even without spaces found. + // No idea if this is 100% correct - at least, looks good. + hasStartSpace := false; + while (Length(AText) > 0) and (AText[1] in [#9, #13, #10, ' ']) do + begin + if AText[1] = ' ' then hasStartSpace := true; // A leading space will be added later + Delete(AText, 1, 1); + end; + + hasEndSpace := false; while (Length(AText) > 0) and (AText[Length(AText)] in [#9, #10, #13, ' ']) do + begin + hasEndSpace := true; // A trailing space will be added later Delete(AText, Length(AText), 1); + end; + if AText = '' then exit; // Replace HTML entities by their counter part UTF8 characters - len := Length(AText); P := @AText[1]; while (P^ <> #0) do begin ch := P^; case ch of + ' ': begin + // collapse multiple spaces to a single space (HTML spec) + // http://stackoverflow.com/questions/24615355/browser-white-space-rendering + Result := Result + ' '; + inc(P); + while (P^ = ' ') do inc(P); + dec(P); + end; '&': begin inc(P); if (P <> nil) and IsHTMLEntity(P, ent) then @@ -414,6 +432,10 @@ begin end; inc(P); end; + + // Add leading and trailing spaces from above. + if hasStartSpace then Result := ' ' + Result; + if hasEndSpace then Result := Result + ' '; end;