diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /sw/qa/extras/tiledrendering | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
22 files changed, 3434 insertions, 0 deletions
diff --git a/sw/qa/extras/tiledrendering/data/2-pages.odt b/sw/qa/extras/tiledrendering/data/2-pages.odt Binary files differnew file mode 100644 index 000000000..04953e5ed --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/2-pages.odt diff --git a/sw/qa/extras/tiledrendering/data/drop_down_form_field.odt b/sw/qa/extras/tiledrendering/data/drop_down_form_field.odt Binary files differnew file mode 100644 index 000000000..7793aff4e --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/drop_down_form_field.odt diff --git a/sw/qa/extras/tiledrendering/data/drop_down_form_field2.odt b/sw/qa/extras/tiledrendering/data/drop_down_form_field2.odt Binary files differnew file mode 100644 index 000000000..7793aff4e --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/drop_down_form_field2.odt diff --git a/sw/qa/extras/tiledrendering/data/drop_down_form_field_noitem.odt b/sw/qa/extras/tiledrendering/data/drop_down_form_field_noitem.odt Binary files differnew file mode 100644 index 000000000..c0b703320 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/drop_down_form_field_noitem.odt diff --git a/sw/qa/extras/tiledrendering/data/drop_down_form_field_noselection.odt b/sw/qa/extras/tiledrendering/data/drop_down_form_field_noselection.odt Binary files differnew file mode 100644 index 000000000..0c433c647 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/drop_down_form_field_noselection.odt diff --git a/sw/qa/extras/tiledrendering/data/dummy.fodt b/sw/qa/extras/tiledrendering/data/dummy.fodt new file mode 100644 index 000000000..79a34d514 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/dummy.fodt @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:body> + <office:text> + <text:p>Aaa bbb.</text:p> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/tiledrendering/data/fieldmark.docx b/sw/qa/extras/tiledrendering/data/fieldmark.docx Binary files differnew file mode 100644 index 000000000..02748bb7e --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/fieldmark.docx diff --git a/sw/qa/extras/tiledrendering/data/frame.odt b/sw/qa/extras/tiledrendering/data/frame.odt Binary files differnew file mode 100644 index 000000000..167e8f5b1 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/frame.odt diff --git a/sw/qa/extras/tiledrendering/data/hyperlink.odt b/sw/qa/extras/tiledrendering/data/hyperlink.odt Binary files differnew file mode 100644 index 000000000..4a97bf76b --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/hyperlink.odt diff --git a/sw/qa/extras/tiledrendering/data/image-comment.odt b/sw/qa/extras/tiledrendering/data/image-comment.odt Binary files differnew file mode 100644 index 000000000..0852bedab --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/image-comment.odt diff --git a/sw/qa/extras/tiledrendering/data/pagedown-invalidation.odt b/sw/qa/extras/tiledrendering/data/pagedown-invalidation.odt Binary files differnew file mode 100644 index 000000000..0cad2d270 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/pagedown-invalidation.odt diff --git a/sw/qa/extras/tiledrendering/data/redline-notification-during-save.odt b/sw/qa/extras/tiledrendering/data/redline-notification-during-save.odt Binary files differnew file mode 100644 index 000000000..df4c30682 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/redline-notification-during-save.odt diff --git a/sw/qa/extras/tiledrendering/data/removenode_redline_callback.fodt b/sw/qa/extras/tiledrendering/data/removenode_redline_callback.fodt new file mode 100644 index 000000000..ed06348cc --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/removenode_redline_callback.fodt @@ -0,0 +1,306 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><meta:creation-date>2016-05-17T06:56:18.472497792</meta:creation-date><meta:generator>LibreOfficeDev/6.1.0.0.alpha0$Linux_X86_64 LibreOffice_project/8b89db9127aaac53e19b884c3d546be4127ee38e</meta:generator><meta:editing-duration>PT1H57M33S</meta:editing-duration><meta:editing-cycles>32</meta:editing-cycles><dc:date>2018-03-05T02:20:39.602490321</dc:date><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="2" meta:word-count="2" meta:character-count="8" meta:non-whitespace-character-count="8"/></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">32228</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">20348</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">7613</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">5962</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">32226</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">20346</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">1</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">true</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">24907</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item> + <config:config-item config:name="Rsid" config:type="int">1961503</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="FreeSans1" svg:font-family="FreeSans" style:font-family-generic="swiss"/> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Open Sans" svg:font-family="'Open Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Droid Sans" svg:font-family="'Droid Sans'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="FreeSans" svg:font-family="FreeSans" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in" draw:start-line-spacing-horizontal="0.1114in" draw:start-line-spacing-vertical="0.1114in" draw:end-line-spacing-horizontal="0.1114in" draw:end-line-spacing-vertical="0.1114in" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Droid Sans" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="0.4925in" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Droid Sans" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"/> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.1665in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" fo:keep-with-next="always"/> + <style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="14pt" style:font-name-asian="Droid Sans" style:font-family-asian="'Droid Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="FreeSans1" style:font-family-complex="FreeSans" style:font-family-generic-complex="swiss"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.0835in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-name-complex="FreeSans1" style:font-family-complex="FreeSans" style:font-family-generic-complex="swiss" style:font-size-complex="12pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="FreeSans1" style:font-family-complex="FreeSans" style:font-family-generic-complex="swiss"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3in" fo:text-indent="-0.3in" fo:margin-left="0.3in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4in" fo:text-indent="-0.4in" fo:margin-left="0.4in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.5in" fo:margin-left="0.5in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6in" fo:text-indent="-0.6in" fo:margin-left="0.6in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.7in" fo:text-indent="-0.7in" fo:margin-left="0.7in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.8in" fo:text-indent="-0.8in" fo:margin-left="0.8in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9in" fo:text-indent="-0.9in" fo:margin-left="0.9in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1in" fo:text-indent="-1in" fo:margin-left="1in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.1in" fo:text-indent="-1.1in" fo:margin-left="1.1in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.2in" fo:text-indent="-1.2in" fo:margin-left="1.2in"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.1965in" style:num-format="1" text:number-position="left" text:increment="5"/> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="0000614b" officeooo:paragraph-rsid="0000614b" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="00054216" officeooo:paragraph-rsid="00054216" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="001b47cb" officeooo:paragraph-rsid="001b47cb" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="001b47cb" officeooo:paragraph-rsid="0000614b" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="00054216" officeooo:paragraph-rsid="00054216" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="0000614b" officeooo:paragraph-rsid="0000614b" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="8.2681in" fo:page-height="11.6929in" style:num-format="1" style:print-orientation="portrait" fo:margin-top="0.7874in" fo:margin-bottom="0.7874in" fo:margin-left="0.7874in" fo:margin-right="0.7874in" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.278in" style:layout-grid-ruby-height="0.139in" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0in"> + <style:footnote-sep style:width="0.0071in" style:distance-before-sep="0.0398in" style:distance-after-sep="0.0398in" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:tracked-changes text:track-changes="false"> + <text:changed-region xml:id="ct148588784" text:id="ct148588784"> + <text:insertion> + <office:change-info> + <dc:creator>Aron Budea</dc:creator> + <dc:date>2018-02-23T13:32:12</dc:date> + </office:change-info> + </text:insertion> + </text:changed-region> + <text:changed-region xml:id="ct148756000" text:id="ct148756000"> + <text:insertion> + <office:change-info> + <dc:creator>Aron Budea</dc:creator> + <dc:date>2018-02-23T13:32:15</dc:date> + </office:change-info> + </text:insertion> + </text:changed-region> + </text:tracked-changes> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + </text:sequence-decls> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"><text:change-start text:change-id="ct148588784"/>abcd<text:change-end text:change-id="ct148588784"/></text:p> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P2"><text:change-start text:change-id="ct148756000"/>abcd<text:change-end text:change-id="ct148756000"/></text:p> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"/> + </office:text> + </office:body> +</office:document>
\ No newline at end of file diff --git a/sw/qa/extras/tiledrendering/data/search.odt b/sw/qa/extras/tiledrendering/data/search.odt Binary files differnew file mode 100644 index 000000000..76ab2e193 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/search.odt diff --git a/sw/qa/extras/tiledrendering/data/semi-transparent.odt b/sw/qa/extras/tiledrendering/data/semi-transparent.odt Binary files differnew file mode 100644 index 000000000..eb76980e7 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/semi-transparent.odt diff --git a/sw/qa/extras/tiledrendering/data/shape-with-text.fodt b/sw/qa/extras/tiledrendering/data/shape-with-text.fodt new file mode 100644 index 000000000..ce76aaf1b --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/shape-with-text.fodt @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:body> + <office:text> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + </text:sequence-decls> + <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="0" svg:width="4.883cm" svg:height="3.225cm" svg:x="2.602cm" svg:y="1.178cm"> + <text:p>Shape text</text:p> + <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:glue-points="10800 0 3163 3163 0 10800 3163 18437 10800 21600 18437 18437 21600 10800 18437 3163" draw:text-areas="3163 3163 18437 18437" draw:type="ellipse" draw:enhanced-path="U 10800 10800 10800 10800 0 360 Z N"/> + </draw:custom-shape>Hello.</text:p> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/tiledrendering/data/shape.fodt b/sw/qa/extras/tiledrendering/data/shape.fodt new file mode 100644 index 000000000..feefe48bc --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/shape.fodt @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:body> + <office:text> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + </text:sequence-decls> + <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="0" svg:width="4.883cm" svg:height="3.225cm" svg:x="2.602cm" svg:y="1.178cm"> + <text:p/> + <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:glue-points="10800 0 3163 3163 0 10800 3163 18437 10800 21600 18437 18437 21600 10800 18437 3163" draw:text-areas="3163 3163 18437 18437" draw:type="ellipse" draw:enhanced-path="U 10800 10800 10800 10800 0 360 Z N"/> + </draw:custom-shape>Hello.</text:p> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/tiledrendering/data/splitnode_redline_callback.fodt b/sw/qa/extras/tiledrendering/data/splitnode_redline_callback.fodt new file mode 100644 index 000000000..bffc3a42c --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/splitnode_redline_callback.fodt @@ -0,0 +1,294 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><meta:creation-date>2016-05-17T06:56:18.472497792</meta:creation-date><meta:generator>LibreOfficeDev/6.1.0.0.alpha0$Linux_X86_64 LibreOffice_project/d64ce643275e0b2b0dea9e532fc261391dc8793c</meta:generator><meta:editing-duration>PT1H57M11S</meta:editing-duration><meta:editing-cycles>31</meta:editing-cycles><dc:date>2018-03-01T05:44:45.452664252</dc:date><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="2" meta:word-count="2" meta:character-count="8" meta:non-whitespace-character-count="8"/></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">32228</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">20348</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">7613</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">8846</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">32226</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">20346</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">1</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">true</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">24907</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">true</config:config-item> + <config:config-item config:name="Rsid" config:type="int">1952207</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">false</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"/> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="FreeSans1" svg:font-family="FreeSans" style:font-family-generic="swiss"/> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Open Sans" svg:font-family="'Open Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Droid Sans" svg:font-family="'Droid Sans'" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="FreeSans" svg:font-family="FreeSans" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.1181in" draw:shadow-offset-y="0.1181in" draw:start-line-spacing-horizontal="0.1114in" draw:start-line-spacing-vertical="0.1114in" draw:end-line-spacing-horizontal="0.1114in" draw:end-line-spacing-vertical="0.1114in" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Droid Sans" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="0.4925in" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" fo:country="DE" style:letter-kerning="true" style:font-name-asian="Droid Sans" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"/> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.1665in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" fo:keep-with-next="always"/> + <style:text-properties style:font-name="Liberation Sans" fo:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="14pt" style:font-name-asian="Droid Sans" style:font-family-asian="'Droid Sans'" style:font-family-generic-asian="system" style:font-pitch-asian="variable" style:font-size-asian="14pt" style:font-name-complex="FreeSans" style:font-family-complex="FreeSans" style:font-family-generic-complex="system" style:font-pitch-complex="variable" style:font-size-complex="14pt"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties fo:margin-top="0in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="FreeSans1" style:font-family-complex="FreeSans" style:font-family-generic-complex="swiss"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.0835in" fo:margin-bottom="0.0835in" loext:contextual-spacing="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="12pt" fo:font-style="italic" style:font-size-asian="12pt" style:font-style-asian="italic" style:font-name-complex="FreeSans1" style:font-family-complex="FreeSans" style:font-family-generic-complex="swiss" style:font-size-complex="12pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="FreeSans1" style:font-family-complex="FreeSans" style:font-family-generic-complex="swiss"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3in" fo:text-indent="-0.3in" fo:margin-left="0.3in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4in" fo:text-indent="-0.4in" fo:margin-left="0.4in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.5in" fo:text-indent="-0.5in" fo:margin-left="0.5in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6in" fo:text-indent="-0.6in" fo:margin-left="0.6in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.7in" fo:text-indent="-0.7in" fo:margin-left="0.7in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.8in" fo:text-indent="-0.8in" fo:margin-left="0.8in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9in" fo:text-indent="-0.9in" fo:margin-left="0.9in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1in" fo:text-indent="-1in" fo:margin-left="1in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.1in" fo:text-indent="-1.1in" fo:margin-left="1.1in"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.2in" fo:text-indent="-1.2in" fo:margin-left="1.2in"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.1965in" style:num-format="1" text:number-position="left" text:increment="5"/> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="0000614b" officeooo:paragraph-rsid="0000614b" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="00054216" officeooo:paragraph-rsid="00054216" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="001b47cb" officeooo:paragraph-rsid="001b47cb" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="001b47cb" officeooo:paragraph-rsid="0000614b" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Standard"> + <style:text-properties style:font-name="Open Sans" fo:font-size="12pt" officeooo:rsid="00054216" officeooo:paragraph-rsid="00054216" style:font-size-asian="10.5pt" style:font-size-complex="12pt"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="8.2681in" fo:page-height="11.6929in" style:num-format="1" style:print-orientation="portrait" fo:margin-top="0.7874in" fo:margin-bottom="0.7874in" fo:margin-left="0.7874in" fo:margin-right="0.7874in" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.278in" style:layout-grid-ruby-height="0.139in" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0in"> + <style:footnote-sep style:width="0.0071in" style:distance-before-sep="0.0398in" style:distance-after-sep="0.0398in" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:tracked-changes text:track-changes="false"> + <text:changed-region xml:id="ct47155616" text:id="ct47155616"> + <text:insertion> + <office:change-info> + <dc:creator>Aron Budea</dc:creator> + <dc:date>2018-02-23T13:32:12</dc:date> + </office:change-info> + </text:insertion> + </text:changed-region> + <text:changed-region xml:id="ct37269280" text:id="ct37269280"> + <text:insertion> + <office:change-info> + <dc:creator>Aron Budea</dc:creator> + <dc:date>2018-02-23T13:32:15</dc:date> + </office:change-info> + </text:insertion> + </text:changed-region> + </text:tracked-changes> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + </text:sequence-decls> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"><text:change-start text:change-id="ct47155616"/>abcd<text:change-end text:change-id="ct47155616"/></text:p> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P1"/> + <text:p text:style-name="P2"><text:change-start text:change-id="ct37269280"/>abcd<text:change-end text:change-id="ct37269280"/></text:p> + <text:p text:style-name="P2"/> + <text:p text:style-name="P2"/> + </office:text> + </office:body> +</office:document>
\ No newline at end of file diff --git a/sw/qa/extras/tiledrendering/data/tdf114799.docx b/sw/qa/extras/tiledrendering/data/tdf114799.docx Binary files differnew file mode 100644 index 000000000..730ef91dc --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/tdf114799.docx diff --git a/sw/qa/extras/tiledrendering/data/tdf115088.odt b/sw/qa/extras/tiledrendering/data/tdf115088.odt Binary files differnew file mode 100644 index 000000000..b29681eb8 --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/tdf115088.odt diff --git a/sw/qa/extras/tiledrendering/data/tdf117448.fodt b/sw/qa/extras/tiledrendering/data/tdf117448.fodt new file mode 100644 index 000000000..20846d8cd --- /dev/null +++ b/sw/qa/extras/tiledrendering/data/tdf117448.fodt @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:styles> + <style:style style:name="Standard" style:family="paragraph" style:class="text"/> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties fo:margin-top="0pt" fo:margin-bottom="7pt" loext:contextual-spacing="false" fo:line-height="115%"/> + </style:style> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard"> + <style:paragraph-properties fo:margin-top="8pt" fo:margin-bottom="8pt" loext:contextual-spacing="false" fo:line-height="2pt"/> + <style:text-properties fo:color="#000000" loext:opacity="100%" style:font-name="Liberation Serif" fo:font-size="12pt"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"/> + </office:master-styles> + <office:body> + <office:text> + <table:table table:name="Táblázat1" table:style-name="Táblázat1"> + <table:table-column table:style-name="Táblázat1.A"/> + <table:table-row> + <table:table-cell table:style-name="Táblázat1.A1" office:value-type="string"> + <text:p text:style-name="P1">Text without clipping.</text:p> + </table:table-cell> + </table:table-row> + </table:table> + </office:text> + </office:body> +</office:document> diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx new file mode 100644 index 000000000..487def299 --- /dev/null +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -0,0 +1,2762 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <string> +#include <boost/property_tree/json_parser.hpp> + +#include <com/sun/star/frame/DispatchResultState.hpp> +#include <com/sun/star/frame/XDispatchResultListener.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <swmodeltestbase.hxx> +#include <test/helper/transferable.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> +#include <comphelper/dispatchcommand.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/string.hxx> +#include <comphelper/lok.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdview.hxx> +#include <vcl/virdev.hxx> +#include <editeng/editview.hxx> +#include <editeng/outliner.hxx> +#include <svl/srchitem.hxx> +#include <svl/slstitm.hxx> +#include <svl/stritem.hxx> +#include <drawdoc.hxx> +#include <ndtxt.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <UndoManager.hxx> +#include <cmdid.h> +#include <sfx2/viewsh.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/lokhelper.hxx> +#include <redline.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <IDocumentRedlineAccess.hxx> +#include <vcl/scheduler.hxx> +#include <vcl/vclevent.hxx> +#include <vcl/bitmapaccess.hxx> +#include <svx/svxids.hrc> +#include <flddat.hxx> +#include <basesh.hxx> +#include <vcl/ITiledRenderable.hxx> + +static char const DATA_DIRECTORY[] = "/sw/qa/extras/tiledrendering/data/"; + +static std::ostream& operator<<(std::ostream& os, ViewShellId id) +{ + os << static_cast<sal_Int32>(id); + return os; +} + +/// Testsuite for the SwXTextDocument methods implementing the vcl::ITiledRenderable interface. +class SwTiledRenderingTest : public SwModelTestBase +{ +public: + SwTiledRenderingTest(); + virtual void setUp() override; + virtual void tearDown() override; + void testRegisterCallback(); + void testPostKeyEvent(); + void testPostMouseEvent(); + void testSetTextSelection(); + void testGetTextSelection(); + void testSetGraphicSelection(); + void testResetSelection(); + void testInsertShape(); + void testSearch(); + void testSearchViewArea(); + void testSearchTextFrame(); + void testSearchTextFrameWrapAround(); + void testDocumentSizeChanged(); + void testSearchAll(); + void testSearchAllNotifications(); + void testPageDownInvalidation(); + void testPartHash(); + void testViewCursors(); + void testShapeViewCursors(); + void testMissingInvalidation(); + void testViewCursorVisibility(); + void testViewCursorCleanup(); + void testViewLock(); + void testTextEditViewInvalidations(); + void testUndoInvalidations(); + void testUndoLimiting(); + void testUndoShapeLimiting(); + void testUndoDispatch(); + void testUndoRepairDispatch(); + void testShapeTextUndoShells(); + void testShapeTextUndoGroupShells(); + void testTrackChanges(); + void testTrackChangesCallback(); + void testRedlineUpdateCallback(); + void testSetViewGraphicSelection(); + void testCreateViewGraphicSelection(); + void testCreateViewTextSelection(); + void testRedlineColors(); + void testCommentEndTextEdit(); + void testCommentInsert(); + void testCursorPosition(); + void testPaintCallbacks(); + void testUndoRepairResult(); + void testRedoRepairResult(); + void testDisableUndoRepair(); + void testAllTrackedChanges(); + void testDocumentRepair(); + void testPageHeader(); + void testPageFooter(); + void testTdf115088(); + void testRedlineField(); + void testIMESupport(); + void testSplitNodeRedlineCallback(); + void testDeleteNodeRedlineCallback(); + void testVisCursorInvalidation(); + void testDeselectCustomShape(); + void testSemiTransparent(); + void testHighlightNumbering(); + void testClipText(); + void testAnchorTypes(); + void testLanguageStatus(); + void testRedlineNotificationDuringSave(); + void testHyperlink(); + void testFieldmark(); + void testDropDownFormFieldButton(); + void testDropDownFormFieldButtonEditing(); + void testDropDownFormFieldButtonNoSelection(); + void testDropDownFormFieldButtonNoItem(); + + CPPUNIT_TEST_SUITE(SwTiledRenderingTest); + CPPUNIT_TEST(testRegisterCallback); + CPPUNIT_TEST(testPostKeyEvent); + CPPUNIT_TEST(testPostMouseEvent); + CPPUNIT_TEST(testSetTextSelection); + CPPUNIT_TEST(testGetTextSelection); + CPPUNIT_TEST(testSetGraphicSelection); + CPPUNIT_TEST(testResetSelection); + CPPUNIT_TEST(testInsertShape); + CPPUNIT_TEST(testSearch); + CPPUNIT_TEST(testSearchViewArea); + CPPUNIT_TEST(testSearchTextFrame); + CPPUNIT_TEST(testSearchTextFrameWrapAround); + CPPUNIT_TEST(testDocumentSizeChanged); + CPPUNIT_TEST(testSearchAll); + CPPUNIT_TEST(testSearchAllNotifications); + CPPUNIT_TEST(testPageDownInvalidation); + CPPUNIT_TEST(testPartHash); + CPPUNIT_TEST(testViewCursors); + CPPUNIT_TEST(testShapeViewCursors); + CPPUNIT_TEST(testMissingInvalidation); + CPPUNIT_TEST(testViewCursorVisibility); + CPPUNIT_TEST(testViewCursorCleanup); + CPPUNIT_TEST(testViewLock); + CPPUNIT_TEST(testTextEditViewInvalidations); + CPPUNIT_TEST(testUndoInvalidations); + CPPUNIT_TEST(testUndoLimiting); + CPPUNIT_TEST(testUndoShapeLimiting); + CPPUNIT_TEST(testUndoDispatch); + CPPUNIT_TEST(testUndoRepairDispatch); + CPPUNIT_TEST(testShapeTextUndoShells); + CPPUNIT_TEST(testShapeTextUndoGroupShells); + CPPUNIT_TEST(testTrackChanges); + CPPUNIT_TEST(testTrackChangesCallback); + CPPUNIT_TEST(testRedlineUpdateCallback); + CPPUNIT_TEST(testSetViewGraphicSelection); + CPPUNIT_TEST(testCreateViewGraphicSelection); + CPPUNIT_TEST(testCreateViewTextSelection); + CPPUNIT_TEST(testRedlineColors); + CPPUNIT_TEST(testCommentEndTextEdit); + CPPUNIT_TEST(testCommentInsert); + CPPUNIT_TEST(testCursorPosition); + CPPUNIT_TEST(testPaintCallbacks); + CPPUNIT_TEST(testUndoRepairResult); + CPPUNIT_TEST(testRedoRepairResult); + CPPUNIT_TEST(testDisableUndoRepair); + CPPUNIT_TEST(testAllTrackedChanges); + CPPUNIT_TEST(testDocumentRepair); + CPPUNIT_TEST(testPageHeader); + CPPUNIT_TEST(testPageFooter); + CPPUNIT_TEST(testTdf115088); + CPPUNIT_TEST(testRedlineField); + CPPUNIT_TEST(testIMESupport); + CPPUNIT_TEST(testSplitNodeRedlineCallback); + CPPUNIT_TEST(testDeleteNodeRedlineCallback); + CPPUNIT_TEST(testVisCursorInvalidation); + CPPUNIT_TEST(testDeselectCustomShape); + CPPUNIT_TEST(testSemiTransparent); + CPPUNIT_TEST(testHighlightNumbering); + CPPUNIT_TEST(testClipText); + CPPUNIT_TEST(testAnchorTypes); + CPPUNIT_TEST(testLanguageStatus); + CPPUNIT_TEST(testRedlineNotificationDuringSave); + CPPUNIT_TEST(testHyperlink); + CPPUNIT_TEST(testFieldmark); + CPPUNIT_TEST(testDropDownFormFieldButton); + CPPUNIT_TEST(testDropDownFormFieldButtonEditing); + CPPUNIT_TEST(testDropDownFormFieldButtonNoSelection); + CPPUNIT_TEST(testDropDownFormFieldButtonNoItem); + CPPUNIT_TEST_SUITE_END(); + +private: + SwXTextDocument* createDoc(const char* pName = nullptr); + static void callback(int nType, const char* pPayload, void* pData); + void callbackImpl(int nType, const char* pPayload); + tools::Rectangle m_aInvalidation; + Size m_aDocumentSize; + OString m_aTextSelection; + bool m_bFound; + std::vector<OString> m_aSearchResultSelection; + std::vector<int> m_aSearchResultPart; + int m_nSelectionBeforeSearchResult; + int m_nSelectionAfterSearchResult; + int m_nInvalidations; + int m_nRedlineTableSizeChanged; + int m_nRedlineTableEntryModified; + int m_nTrackedChangeIndex; + OString m_sHyperlinkText; + OString m_sHyperlinkLink; + OString m_aFormFieldButton; +}; + +SwTiledRenderingTest::SwTiledRenderingTest() + : m_bFound(true), + m_nSelectionBeforeSearchResult(0), + m_nSelectionAfterSearchResult(0), + m_nInvalidations(0), + m_nRedlineTableSizeChanged(0), + m_nRedlineTableEntryModified(0), + m_nTrackedChangeIndex(-1) +{ +} + +void SwTiledRenderingTest::setUp() +{ + SwModelTestBase::setUp(); + + comphelper::LibreOfficeKit::setActive(true); +} + +void SwTiledRenderingTest::tearDown() +{ + if (mxComponent.is()) + { + SwXTextDocument* pTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + if (pTextDocument) + { + SwWrtShell* pWrtShell = pTextDocument->GetDocShell()->GetWrtShell(); + if (pWrtShell) + { + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + } + } + mxComponent->dispose(); + mxComponent.clear(); + } + comphelper::LibreOfficeKit::setActive(false); + + test::BootstrapFixture::tearDown(); +} + +SwXTextDocument* SwTiledRenderingTest::createDoc(const char* pName) +{ + if (!pName) + loadURL("private:factory/swriter", nullptr); + else + load(DATA_DIRECTORY, pName); + + SwXTextDocument* pTextDocument = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDocument); + pTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + return pTextDocument; +} + +void SwTiledRenderingTest::callback(int nType, const char* pPayload, void* pData) +{ + static_cast<SwTiledRenderingTest*>(pData)->callbackImpl(nType, pPayload); +} + +void SwTiledRenderingTest::callbackImpl(int nType, const char* pPayload) +{ + OString aPayload(pPayload); + switch (nType) + { + case LOK_CALLBACK_INVALIDATE_TILES: + { + if (m_aInvalidation.IsEmpty()) + { + uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload)); + if (OString("EMPTY") == pPayload) + return; + CPPUNIT_ASSERT(aSeq.getLength() == 4 || aSeq.getLength() == 5); + m_aInvalidation.setX(aSeq[0].toInt32()); + m_aInvalidation.setY(aSeq[1].toInt32()); + m_aInvalidation.setWidth(aSeq[2].toInt32()); + m_aInvalidation.setHeight(aSeq[3].toInt32()); + } + ++m_nInvalidations; + } + break; + case LOK_CALLBACK_DOCUMENT_SIZE_CHANGED: + { + uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::createFromAscii(pPayload)); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), aSeq.getLength()); + m_aDocumentSize.setWidth(aSeq[0].toInt32()); + m_aDocumentSize.setHeight(aSeq[1].toInt32()); + } + break; + case LOK_CALLBACK_TEXT_SELECTION: + { + m_aTextSelection = pPayload; + if (m_aSearchResultSelection.empty()) + ++m_nSelectionBeforeSearchResult; + else + ++m_nSelectionAfterSearchResult; + } + break; + case LOK_CALLBACK_SEARCH_NOT_FOUND: + { + m_bFound = false; + } + break; + case LOK_CALLBACK_SEARCH_RESULT_SELECTION: + { + m_aSearchResultSelection.clear(); + boost::property_tree::ptree aTree; + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, aTree); + for (const boost::property_tree::ptree::value_type& rValue : aTree.get_child("searchResultSelection")) + { + m_aSearchResultSelection.emplace_back(rValue.second.get<std::string>("rectangles").c_str()); + m_aSearchResultPart.push_back(std::atoi(rValue.second.get<std::string>("part").c_str())); + } + } + break; + case LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED: + { + ++m_nRedlineTableSizeChanged; + } + break; + case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED: + { + ++m_nRedlineTableEntryModified; + } + break; + case LOK_CALLBACK_STATE_CHANGED: + { + OString aTrackedChangeIndexPrefix(".uno:TrackedChangeIndex="); + if (aPayload.startsWith(aTrackedChangeIndexPrefix)) + { + OString sIndex = aPayload.copy(aTrackedChangeIndexPrefix.getLength()); + if (sIndex.isEmpty()) + m_nTrackedChangeIndex = -1; + else + m_nTrackedChangeIndex = sIndex.toInt32(); + } + } + break; + case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: + { + if (comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation()) + { + boost::property_tree::ptree aTree; + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, aTree); + boost::property_tree::ptree &aChild = aTree.get_child("hyperlink"); + m_sHyperlinkText = aChild.get("text", "").c_str(); + m_sHyperlinkLink = aChild.get("link", "").c_str(); + } + } + break; + case LOK_CALLBACK_FORM_FIELD_BUTTON: + { + m_aFormFieldButton = OString(pPayload); + } + break; + } +} + +void SwTiledRenderingTest::testRegisterCallback() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + // Insert a character at the beginning of the document. + pWrtShell->Insert("x"); + + // Check that the top left 256x256px tile would be invalidated. + CPPUNIT_ASSERT(!m_aInvalidation.IsEmpty()); + tools::Rectangle aTopLeft(0, 0, 256*15, 256*15); // 1 px = 15 twips, assuming 96 DPI. + CPPUNIT_ASSERT(m_aInvalidation.IsOver(aTopLeft)); +} + +void SwTiledRenderingTest::testPostKeyEvent() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // Did we manage to go after the first character? + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), pShellCursor->GetPoint()->nContent.GetIndex()); + + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + // Did we manage to insert the character after the first one? + CPPUNIT_ASSERT_EQUAL(OUString("Axaa bbb."), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); +} + +void SwTiledRenderingTest::testPostMouseEvent() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // Did we manage to go after the first character? + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), pShellCursor->GetPoint()->nContent.GetIndex()); + + Point aStart = pShellCursor->GetSttPos(); + aStart.setX(aStart.getX() - 1000); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + // The new cursor position must be before the first word. + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), pShellCursor->GetPoint()->nContent.GetIndex()); +} + +void SwTiledRenderingTest::testSetTextSelection() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + // Move the cursor into the second word. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 5, /*bBasicCall=*/false); + // Create a selection on the word. + pWrtShell->SelWrd(); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // Did we indeed manage to select the second word? + CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCursor->GetText()); + + // Now use setTextSelection() to move the start of the selection 1000 twips left. + Point aStart = pShellCursor->GetSttPos(); + aStart.setX(aStart.getX() - 1000); + pXTextDocument->setTextSelection(LOK_SETTEXTSELECTION_START, aStart.getX(), aStart.getY()); + // The new selection must include the first word, too -- but not the ending dot. + CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb"), pShellCursor->GetText()); + + // Next: test that LOK_SETTEXTSELECTION_RESET + LOK_SETTEXTSELECTION_END can be used to create a selection. + pXTextDocument->setTextSelection(LOK_SETTEXTSELECTION_RESET, aStart.getX(), aStart.getY()); + pXTextDocument->setTextSelection(LOK_SETTEXTSELECTION_END, aStart.getX() + 1000, aStart.getY()); + CPPUNIT_ASSERT_EQUAL(OUString("Aaa b"), pShellCursor->GetText()); +} + +void SwTiledRenderingTest::testGetTextSelection() +{ + SwXTextDocument* pXTextDocument = createDoc("shape-with-text.fodt"); + // No crash, just empty output for unexpected mime type. + CPPUNIT_ASSERT_EQUAL(OString(), apitest::helper::transferable::getTextSelection(pXTextDocument->getSelection(), "foo/bar")); + + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + // Move the cursor into the first word. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 2, /*bBasicCall=*/false); + // Create a selection by on the word. + pWrtShell->SelWrd(); + + // Make sure that we selected text from the body text. + CPPUNIT_ASSERT_EQUAL(OString("Hello"), apitest::helper::transferable::getTextSelection(pXTextDocument->getSelection(), "text/plain;charset=utf-8")); + + // Make sure we produce something for HTML. + CPPUNIT_ASSERT(!apitest::helper::transferable::getTextSelection(pXTextDocument->getSelection(), "text/html").isEmpty()); + + // Now select some shape text and check again. + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + pView->SdrBeginTextEdit(pObject); + CPPUNIT_ASSERT(pView->GetTextEditObject()); + EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView(); + ESelection aWordSelection(0, 0, 0, 5); + rEditView.SetSelection(aWordSelection); + CPPUNIT_ASSERT_EQUAL(OString("Shape"), apitest::helper::transferable::getTextSelection(pXTextDocument->getSelection(), "text/plain;charset=utf-8")); +} + +void SwTiledRenderingTest::testSetGraphicSelection() +{ + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + pWrtShell->SelectObj(Point(), 0, pObject); + SdrHdlList handleList(nullptr); + pObject->AddToHdlList(handleList); + // Make sure the rectangle has 8 handles: at each corner and at the center of each edge. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(8), handleList.GetHdlCount()); + // Take the bottom center one. + SdrHdl* pHdl = handleList.GetHdl(6); + CPPUNIT_ASSERT_EQUAL(int(SdrHdlKind::Lower), static_cast<int>(pHdl->GetKind())); + tools::Rectangle aShapeBefore = pObject->GetSnapRect(); + // Resize. + pXTextDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_START, pHdl->GetPos().getX(), pHdl->GetPos().getY()); + pXTextDocument->setGraphicSelection(LOK_SETGRAPHICSELECTION_END, pHdl->GetPos().getX(), pHdl->GetPos().getY() + 1000); + tools::Rectangle aShapeAfter = pObject->GetSnapRect(); + // Check that a resize happened, but aspect ratio is not kept. + CPPUNIT_ASSERT_EQUAL(aShapeBefore.getWidth(), aShapeAfter.getWidth()); + CPPUNIT_ASSERT_EQUAL(aShapeBefore.getHeight() + 1000, aShapeAfter.getHeight()); +} + +void SwTiledRenderingTest::testResetSelection() +{ + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + // Select one character. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 1, /*bBasicCall=*/false); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // We have a text selection. + CPPUNIT_ASSERT(pShellCursor->HasMark()); + + pXTextDocument->resetSelection(); + // We no longer have a text selection. + CPPUNIT_ASSERT(!pShellCursor->HasMark()); + + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + Point aPoint = pObject->GetSnapRect().Center(); + // Select the shape. + pWrtShell->EnterSelFrameMode(&aPoint); + // We have a graphic selection. + CPPUNIT_ASSERT(pWrtShell->IsSelFrameMode()); + + pXTextDocument->resetSelection(); + // We no longer have a graphic selection. + CPPUNIT_ASSERT(!pWrtShell->IsSelFrameMode()); +} + +void SwTiledRenderingTest::testInsertShape() +{ + SwXTextDocument* pXTextDocument = createDoc("2-pages.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + + pXTextDocument->setClientVisibleArea(tools::Rectangle(0, 0, 10000, 4000)); + comphelper::dispatchCommand(".uno:BasicShapes.circle", uno::Sequence<beans::PropertyValue>()); + + // check that the shape was inserted in the visible area, not outside + IDocumentDrawModelAccess &rDrawModelAccess = pWrtShell->GetDoc()->getIDocumentDrawModelAccess(); + SdrPage* pPage = rDrawModelAccess.GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + CPPUNIT_ASSERT_EQUAL(tools::Rectangle(3302, 302, 6698, 3698), pObject->GetSnapRect()); + + // check that it is in the foreground layer + CPPUNIT_ASSERT_EQUAL(rDrawModelAccess.GetHeavenId().get(), pObject->GetLayer().get()); +} + +static void lcl_search(bool bBackward) +{ + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"SearchItem.SearchString", uno::makeAny(OUString("shape"))}, + {"SearchItem.Backward", uno::makeAny(bBackward)} + })); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); +} + +void SwTiledRenderingTest::testSearch() +{ + SwXTextDocument* pXTextDocument = createDoc("search.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + std::size_t nNode = pWrtShell->getShellCursor(false)->Start()->nNode.GetNode().GetIndex(); + + // First hit, in the second paragraph, before the shape. + lcl_search(false); + CPPUNIT_ASSERT(!pWrtShell->GetDrawView()->GetTextEditObject()); + std::size_t nActual = pWrtShell->getShellCursor(false)->Start()->nNode.GetNode().GetIndex(); + CPPUNIT_ASSERT_EQUAL(nNode + 1, nActual); + /// Make sure we get search result selection for normal find as well, not only find all. + CPPUNIT_ASSERT(!m_aSearchResultSelection.empty()); + + // Next hit, in the shape. + lcl_search(false); + CPPUNIT_ASSERT(pWrtShell->GetDrawView()->GetTextEditObject()); + + // Next hit, in the shape, still. + lcl_search(false); + CPPUNIT_ASSERT(pWrtShell->GetDrawView()->GetTextEditObject()); + + // Last hit, in the last paragraph, after the shape. + lcl_search(false); + CPPUNIT_ASSERT(!pWrtShell->GetDrawView()->GetTextEditObject()); + nActual = pWrtShell->getShellCursor(false)->Start()->nNode.GetNode().GetIndex(); + CPPUNIT_ASSERT_EQUAL(nNode + 7, nActual); + + // Now change direction and make sure that the first 2 hits are in the shape, but not the 3rd one. + lcl_search(true); + CPPUNIT_ASSERT(pWrtShell->GetDrawView()->GetTextEditObject()); + lcl_search(true); + CPPUNIT_ASSERT(pWrtShell->GetDrawView()->GetTextEditObject()); + lcl_search(true); + CPPUNIT_ASSERT(!pWrtShell->GetDrawView()->GetTextEditObject()); + nActual = pWrtShell->getShellCursor(false)->Start()->nNode.GetNode().GetIndex(); + CPPUNIT_ASSERT_EQUAL(nNode + 1, nActual); +} + +void SwTiledRenderingTest::testSearchViewArea() +{ + SwXTextDocument* pXTextDocument = createDoc("search.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + // Go to the second page, 1-based. + pWrtShell->GotoPage(2, false); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // Get the ~top left corner of the second page. + Point aPoint = pShellCursor->GetSttPos(); + + // Go back to the first page, search while the cursor is there, but the + // visible area is the second page. + pWrtShell->GotoPage(1, false); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"SearchItem.SearchString", uno::makeAny(OUString("Heading"))}, + {"SearchItem.Backward", uno::makeAny(false)}, + {"SearchItem.SearchStartPointX", uno::makeAny(static_cast<sal_Int32>(aPoint.getX()))}, + {"SearchItem.SearchStartPointY", uno::makeAny(static_cast<sal_Int32>(aPoint.getY()))} + })); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); + // This was just "Heading", i.e. SwView::SearchAndWrap() did not search from only the top of the second page. + CPPUNIT_ASSERT_EQUAL(OUString("Heading on second page"), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); +} + +void SwTiledRenderingTest::testSearchTextFrame() +{ + SwXTextDocument* pXTextDocument = createDoc("search.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"SearchItem.SearchString", uno::makeAny(OUString("TextFrame"))}, + {"SearchItem.Backward", uno::makeAny(false)}, + })); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); + // This was empty: nothing was highlighted after searching for 'TextFrame'. + CPPUNIT_ASSERT(!m_aTextSelection.isEmpty()); +} + +void SwTiledRenderingTest::testSearchTextFrameWrapAround() +{ + SwXTextDocument* pXTextDocument = createDoc("search.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"SearchItem.SearchString", uno::makeAny(OUString("TextFrame"))}, + {"SearchItem.Backward", uno::makeAny(false)}, + })); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); + CPPUNIT_ASSERT(m_bFound); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); + // This failed, i.e. the second time 'not found' was reported, instead of wrapping around. + CPPUNIT_ASSERT(m_bFound); +} + +void SwTiledRenderingTest::testDocumentSizeChanged() +{ + // Get the current document size. + SwXTextDocument* pXTextDocument = createDoc("2-pages.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + Size aSize = pXTextDocument->getDocumentSize(); + + // Delete the second page and see how the size changes. + pWrtShell->Down(false); + pWrtShell->DelLeft(); + // Document width should not change, this was 0. + CPPUNIT_ASSERT_EQUAL(aSize.getWidth(), m_aDocumentSize.getWidth()); + // Document height should be smaller now. + CPPUNIT_ASSERT(aSize.getHeight() > m_aDocumentSize.getHeight()); +} + +void SwTiledRenderingTest::testSearchAll() +{ + SwXTextDocument* pXTextDocument = createDoc("search.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"SearchItem.SearchString", uno::makeAny(OUString("shape"))}, + {"SearchItem.Backward", uno::makeAny(false)}, + {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))}, + })); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); + // This was 0; should be 2 results in the body text. + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), m_aSearchResultSelection.size()); + // Writer documents are always a single part. + CPPUNIT_ASSERT_EQUAL(0, m_aSearchResultPart[0]); +} + +void SwTiledRenderingTest::testSearchAllNotifications() +{ + SwXTextDocument* pXTextDocument = createDoc("search.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + // Reset notification counter before search. + m_nSelectionBeforeSearchResult = 0; + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"SearchItem.SearchString", uno::makeAny(OUString("shape"))}, + {"SearchItem.Backward", uno::makeAny(false)}, + {"SearchItem.Command", uno::makeAny(static_cast<sal_uInt16>(SvxSearchCmd::FIND_ALL))}, + })); + comphelper::dispatchCommand(".uno:ExecuteSearch", aPropertyValues); + Scheduler::ProcessEventsToIdle(); + + // This was 5, make sure that we get no notifications about selection changes during search. + CPPUNIT_ASSERT_EQUAL(0, m_nSelectionBeforeSearchResult); + // But we do get the selection afterwards. + CPPUNIT_ASSERT(m_nSelectionAfterSearchResult > 0); +} + +void SwTiledRenderingTest::testPageDownInvalidation() +{ + SwXTextDocument* pXTextDocument = createDoc("pagedown-invalidation.odt"); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {".uno:HideWhitespace", uno::makeAny(true)}, + })); + pXTextDocument->initializeForTiledRendering(aPropertyValues); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + comphelper::dispatchCommand(".uno:PageDown", uno::Sequence<beans::PropertyValue>()); + + // This was 2. + CPPUNIT_ASSERT_EQUAL(0, m_nInvalidations); +} + +void SwTiledRenderingTest::testPartHash() +{ + SwXTextDocument* pXTextDocument = createDoc("pagedown-invalidation.odt"); + int nParts = pXTextDocument->getParts(); + for (int it = 0; it < nParts; it++) + { + CPPUNIT_ASSERT(!pXTextDocument->getPartHash(it).isEmpty()); + } +} + +namespace { + +/// A view callback tracks callbacks invoked on one specific view. +class ViewCallback +{ + SfxViewShell* mpViewShell; + int mnView; +public: + bool m_bOwnCursorInvalidated; + int m_nOwnCursorInvalidatedBy; + bool m_bOwnCursorAtOrigin; + tools::Rectangle m_aOwnCursor; + bool m_bViewCursorInvalidated; + tools::Rectangle m_aViewCursor; + bool m_bOwnSelectionSet; + bool m_bViewSelectionSet; + OString m_aViewSelection; + bool m_bTilesInvalidated; + bool m_bViewCursorVisible; + bool m_bGraphicViewSelection; + bool m_bGraphicSelection; + bool m_bViewLock; + /// Set if any callback was invoked. + bool m_bCalled; + /// Redline table size changed payload + boost::property_tree::ptree m_aRedlineTableChanged; + /// Redline table modified payload + boost::property_tree::ptree m_aRedlineTableModified; + /// Post-it / annotation payload. + boost::property_tree::ptree m_aComment; + + ViewCallback(SfxViewShell* pViewShell, std::function<void(ViewCallback&)> const & rBeforeInstallFunc = {}) + : m_bOwnCursorInvalidated(false), + m_nOwnCursorInvalidatedBy(-1), + m_bOwnCursorAtOrigin(false), + m_bViewCursorInvalidated(false), + m_bOwnSelectionSet(false), + m_bViewSelectionSet(false), + m_bTilesInvalidated(false), + m_bViewCursorVisible(false), + m_bGraphicViewSelection(false), + m_bGraphicSelection(false), + m_bViewLock(false), + m_bCalled(false) + { + // Because one call-site wants to set the bool fields up before the callback is installed + if (rBeforeInstallFunc) + rBeforeInstallFunc(*this); + + mpViewShell = pViewShell; + mpViewShell->registerLibreOfficeKitViewCallback(&ViewCallback::callback, this); + mnView = SfxLokHelper::getView(); + } + + ~ViewCallback() + { + SfxLokHelper::setView(mnView); + mpViewShell->registerLibreOfficeKitViewCallback(nullptr, nullptr); + } + + static void callback(int nType, const char* pPayload, void* pData) + { + static_cast<ViewCallback*>(pData)->callbackImpl(nType, pPayload); + } + + void callbackImpl(int nType, const char* pPayload) + { + OString aPayload(pPayload); + m_bCalled = true; + switch (nType) + { + case LOK_CALLBACK_INVALIDATE_TILES: + { + m_bTilesInvalidated = true; + } + break; + case LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR: + { + m_bOwnCursorInvalidated = true; + + OString sRect; + if(comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation()) + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + sRect = aTree.get_child("rectangle").get_value<std::string>().c_str(); + m_nOwnCursorInvalidatedBy = aTree.get_child("viewId").get_value<int>(); + } + else + sRect = aPayload; + uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::fromUtf8(sRect)); + if (OString("EMPTY") == pPayload) + return; + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), aSeq.getLength()); + m_aOwnCursor.setX(aSeq[0].toInt32()); + m_aOwnCursor.setY(aSeq[1].toInt32()); + m_aOwnCursor.setWidth(aSeq[2].toInt32()); + m_aOwnCursor.setHeight(aSeq[3].toInt32()); + if (m_aOwnCursor.getX() == 0 && m_aOwnCursor.getY() == 0) + m_bOwnCursorAtOrigin = true; + } + break; + case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR: + { + m_bViewCursorInvalidated = true; + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + OString aRect = aTree.get_child("rectangle").get_value<std::string>().c_str(); + + uno::Sequence<OUString> aSeq = comphelper::string::convertCommaSeparated(OUString::fromUtf8(aRect)); + if (OString("EMPTY") == pPayload) + return; + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(4), aSeq.getLength()); + m_aViewCursor.setX(aSeq[0].toInt32()); + m_aViewCursor.setY(aSeq[1].toInt32()); + m_aViewCursor.setWidth(aSeq[2].toInt32()); + m_aViewCursor.setHeight(aSeq[3].toInt32()); + } + break; + case LOK_CALLBACK_TEXT_SELECTION: + { + m_bOwnSelectionSet = true; + } + break; + case LOK_CALLBACK_TEXT_VIEW_SELECTION: + { + m_bViewSelectionSet = true; + m_aViewSelection = aPayload; + } + break; + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + m_bViewCursorVisible = aTree.get_child("visible").get_value<std::string>() == "true"; + } + break; + case LOK_CALLBACK_GRAPHIC_VIEW_SELECTION: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + m_bGraphicViewSelection = aTree.get_child("selection").get_value<std::string>() != "EMPTY"; + } + break; + case LOK_CALLBACK_GRAPHIC_SELECTION: + { + m_bGraphicSelection = aPayload != "EMPTY"; + } + break; + case LOK_CALLBACK_VIEW_LOCK: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + m_bViewLock = aTree.get_child("rectangle").get_value<std::string>() != "EMPTY"; + } + break; + case LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED: + { + m_aRedlineTableChanged.clear(); + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, m_aRedlineTableChanged); + m_aRedlineTableChanged = m_aRedlineTableChanged.get_child("redline"); + } + break; + case LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED: + { + m_aRedlineTableModified.clear(); + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, m_aRedlineTableModified); + m_aRedlineTableModified = m_aRedlineTableModified.get_child("redline"); + } + break; + case LOK_CALLBACK_COMMENT: + { + m_aComment.clear(); + std::stringstream aStream(pPayload); + boost::property_tree::read_json(aStream, m_aComment); + m_aComment = m_aComment.get_child("comment"); + } + break; + } + } +}; + +class TestResultListener : public cppu::WeakImplHelper<css::frame::XDispatchResultListener> +{ +public: + sal_uInt32 m_nDocRepair; + + TestResultListener() : m_nDocRepair(0) + { + } + + virtual void SAL_CALL dispatchFinished(const css::frame::DispatchResultEvent& rEvent) override + { + if (rEvent.State == frame::DispatchResultState::SUCCESS) + { + rEvent.Result >>= m_nDocRepair; + } + } + + virtual void SAL_CALL disposing(const css::lang::EventObject&) override + { + } +}; + +} + +void SwTiledRenderingTest::testMissingInvalidation() +{ + // Create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + ViewCallback aView2(SfxViewShell::Current()); + int nView2 = SfxLokHelper::getView(); + + // First view: put the cursor into the first word. + SfxLokHelper::setView(nView1); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + + // Second view: select the first word. + SfxLokHelper::setView(nView2); + CPPUNIT_ASSERT(pXTextDocument->GetDocShell()->GetWrtShell() != pWrtShell); + pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + pWrtShell->SelWrd(); + + // Now delete the selected word and make sure both views are invalidated. + aView1.m_bTilesInvalidated = false; + aView2.m_bTilesInvalidated = false; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::DELETE); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::DELETE); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(aView1.m_bTilesInvalidated); + CPPUNIT_ASSERT(aView2.m_bTilesInvalidated); +} + +void SwTiledRenderingTest::testViewCursors() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + SfxLokHelper::createView(); + ViewCallback aView2(SfxViewShell::Current()); + CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated); + // This failed: the cursor position of view1 was only known to view2 once + // it changed. + CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated); + + // Make sure that aView1 gets a view-only selection notification, while + // aView2 gets a real selection notification. + aView1.m_bOwnSelectionSet = false; + aView1.m_bViewSelectionSet = false; + aView2.m_bOwnSelectionSet = false; + aView2.m_bViewSelectionSet = false; + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + // Move the cursor into the second word. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 5, /*bBasicCall=*/false); + // Create a selection on the word. + pWrtShell->SelWrd(); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // Did we indeed manage to select the second word? + CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCursor->GetText()); + CPPUNIT_ASSERT(!aView1.m_bOwnSelectionSet); + // This failed, aView1 did not get notification about selection changes in + // aView2. + CPPUNIT_ASSERT(aView1.m_bViewSelectionSet); + CPPUNIT_ASSERT(aView2.m_bOwnSelectionSet); + CPPUNIT_ASSERT(!aView2.m_bViewSelectionSet); +} + +void SwTiledRenderingTest::testShapeViewCursors() +{ + // Load a document and create a view, so we have 2 ones. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2(SfxViewShell::Current()); + SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); + + // Start shape text in the second view. + SdrPage* pPage = pWrtShell2->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell2->GetDrawView(); + pWrtShell2->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell2->GetWin()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + // Press a key in the second view, while the first one observes this. + aView1.m_bViewCursorInvalidated = false; + aView2.m_bOwnCursorInvalidated = false; + const tools::Rectangle aLastOwnCursor1 = aView1.m_aOwnCursor; + const tools::Rectangle aLastViewCursor1 = aView1.m_aViewCursor; + const tools::Rectangle aLastOwnCursor2 = aView2.m_aOwnCursor; + const tools::Rectangle aLastViewCursor2 = aView2.m_aViewCursor; + + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'y', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'y', 0); + Scheduler::ProcessEventsToIdle(); + // Make sure that aView1 gets a view-only cursor notification, while + // aView2 gets a real cursor notification. + CPPUNIT_ASSERT_EQUAL(aView1.m_aOwnCursor, aLastOwnCursor1); + CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated && aLastViewCursor1 != aView1.m_aViewCursor); + CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated && aLastOwnCursor2 != aView2.m_aOwnCursor); + CPPUNIT_ASSERT_EQUAL(aLastViewCursor2, aView2.m_aViewCursor); +} + +void SwTiledRenderingTest::testViewCursorVisibility() +{ + // Load a document that has a shape and create two views. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2(SfxViewShell::Current()); + // This failed, initially the view cursor in the second view wasn't visible. + CPPUNIT_ASSERT(aView2.m_bViewCursorVisible); + + // Click on the shape in the second view. + aView1.m_bViewCursorVisible = true; + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + Point aCenter = pObject->GetSnapRect().Center(); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aCenter.getX(), aCenter.getY(), 1, MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aCenter.getX(), aCenter.getY(), 1, MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + // Make sure the "view/text" cursor of the first view gets a notification. + CPPUNIT_ASSERT(!aView1.m_bViewCursorVisible); +} + +void SwTiledRenderingTest::testViewCursorCleanup() +{ + // Load a document that has a shape and create two views. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + int nView2 = SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + { + ViewCallback aView2(SfxViewShell::Current()); + + // Click on the shape in the second view. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + Point aCenter = pObject->GetSnapRect().Center(); + aView1.m_bGraphicViewSelection = false; + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aCenter.getX(), aCenter.getY(), 1, MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aCenter.getX(), aCenter.getY(), 1, MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + // Make sure there is a graphic view selection on the first view. + CPPUNIT_ASSERT(aView1.m_bGraphicViewSelection); + } + // Now destroy the second view. + SfxLokHelper::destroyView(nView2); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), SfxLokHelper::getViewsCount()); + // Make sure that the graphic view selection on the first view is cleaned up. + CPPUNIT_ASSERT(!aView1.m_bGraphicViewSelection); +} + +void SwTiledRenderingTest::testViewLock() +{ + // Load a document that has a shape and create two views. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2(SfxViewShell::Current()); + + // Begin text edit in the second view and assert that the first gets a lock + // notification. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + aView1.m_bViewLock = false; + pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell->GetWin()); + CPPUNIT_ASSERT(aView1.m_bViewLock); + + // End text edit in the second view, and assert that the lock is removed in + // the first view. + pWrtShell->EndTextEdit(); + CPPUNIT_ASSERT(!aView1.m_bViewLock); +} + +void SwTiledRenderingTest::testTextEditViewInvalidations() +{ + // Load a document that has a shape and create two views. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2(SfxViewShell::Current()); + + // Begin text edit in the second view. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell->GetWin()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + + // Assert that both views are invalidated when pressing a key while in text edit. + aView1.m_bTilesInvalidated = false; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'y', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'y', 0); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT(aView1.m_bTilesInvalidated); + + pWrtShell->EndTextEdit(); +} + +void SwTiledRenderingTest::testUndoInvalidations() +{ + // Load a document and create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2(SfxViewShell::Current()); + SfxLokHelper::setView(nView1); + + // Insert a character the end of the document. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->EndOfSection(); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0); + Scheduler::ProcessEventsToIdle(); + // ProcessEventsToIdle resets the view; set it again + SfxLokHelper::setView(nView1); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb.c"), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); + + // Undo and assert that both views are invalidated. + aView1.m_bTilesInvalidated = false; + aView2.m_bTilesInvalidated = false; + comphelper::dispatchCommand(".uno:Undo", {}); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(aView1.m_bTilesInvalidated); + // Undo was dispatched on the first view, this second view was not invalidated. + CPPUNIT_ASSERT(aView2.m_bTilesInvalidated); +} + +void SwTiledRenderingTest::testUndoLimiting() +{ + // Load a document and create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell1 = pXTextDocument->GetDocShell()->GetWrtShell(); + int nView1 = SfxLokHelper::getView(); + int nView2 = SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + + // Insert a character the end of the document in the second view. + SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell2->EndOfSection(); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0); + Scheduler::ProcessEventsToIdle(); + SwShellCursor* pShellCursor = pWrtShell2->getShellCursor(false); + CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb.c"), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); + + // Assert that the first view can't undo, but the second view can. + CPPUNIT_ASSERT(!pWrtShell1->GetLastUndoInfo(nullptr, nullptr, &pWrtShell1->GetView())); + CPPUNIT_ASSERT(pWrtShell2->GetLastUndoInfo(nullptr, nullptr, &pWrtShell2->GetView())); + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +void SwTiledRenderingTest::testUndoShapeLimiting() +{ + // Load a document and create a view. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + SwWrtShell* pWrtShell1 = pXTextDocument->GetDocShell()->GetWrtShell(); + int nView1 = SfxLokHelper::getView(); + int nView2 = SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); + + // Start shape text in the second view. + SdrPage* pPage = pWrtShell2->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell2->GetDrawView(); + pWrtShell2->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell2->GetWin()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + + // Assert that the first view can't and the second view can undo the insertion. + SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); + sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); + rUndoManager.SetView(&pWrtShell1->GetView()); + // This was 1: first view could undo the change of the second view. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rUndoManager.GetUndoActionCount()); + rUndoManager.SetView(&pWrtShell2->GetView()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); + + pWrtShell2->EndTextEdit(); + rUndoManager.SetView(nullptr); + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +void SwTiledRenderingTest::testUndoDispatch() +{ + // Load a document and create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + int nView2 = SfxLokHelper::getView(); + + // Insert a character in the first view. + SfxLokHelper::setView(nView1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0); + Scheduler::ProcessEventsToIdle(); + + // Click before the first word in the second view. + SfxLokHelper::setView(nView2); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + Point aStart = pShellCursor->GetSttPos(); + aStart.setX(aStart.getX() - 1000); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + uno::Reference<frame::XDesktop2> xDesktop = frame::Desktop::create(comphelper::getProcessComponentContext()); + uno::Reference<frame::XFrame> xFrame2 = xDesktop->getActiveFrame(); + + // Now switch back to the first view, and make sure that the active frame is updated. + SfxLokHelper::setView(nView1); + uno::Reference<frame::XFrame> xFrame1 = xDesktop->getActiveFrame(); + // This failed: setView() did not update the active frame. + CPPUNIT_ASSERT(xFrame1 != xFrame2); + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +void SwTiledRenderingTest::testUndoRepairDispatch() +{ + // Load a document and create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + int nView2 = SfxLokHelper::getView(); + + // Insert a character in the first view. + SfxLokHelper::setView(nView1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0); + Scheduler::ProcessEventsToIdle(); + + // Assert that by default the second view can't undo the action. + SfxLokHelper::setView(nView2); + SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); + sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); + comphelper::dispatchCommand(".uno:Undo", {}); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); + + // But the same is allowed in repair mode. + SfxLokHelper::setView(nView2); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"Repair", uno::makeAny(true)} + })); + comphelper::dispatchCommand(".uno:Undo", aPropertyValues); + Scheduler::ProcessEventsToIdle(); + // This was 1: repair mode couldn't undo the action, either. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), rUndoManager.GetUndoActionCount()); + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +void SwTiledRenderingTest::testShapeTextUndoShells() +{ + // Load a document and create a view. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + sal_Int32 nView1 = SfxLokHelper::getView(); + + // Begin text edit. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell->GetWin()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + + // Make sure that the undo item remembers who created it. + SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); + sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rUndoManager.GetUndoActionCount()); + // This was -1: the view shell id for the undo action wasn't known. + CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), rUndoManager.GetUndoAction()->GetViewShellId()); +} + +void SwTiledRenderingTest::testShapeTextUndoGroupShells() +{ + // Load a document and create a view. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + sal_Int32 nView1 = SfxLokHelper::getView(); + + // Begin text edit. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell->GetWin()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::BACKSPACE); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::BACKSPACE); + Scheduler::ProcessEventsToIdle(); + + // Make sure that the undo item remembers who created it. + SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); + sw::UndoManager& rUndoManager = pDoc->GetUndoManager(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rUndoManager.GetUndoActionCount()); + // This was -1: the view shell id for the (top) undo list action wasn't known. + CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), rUndoManager.GetUndoAction()->GetViewShellId()); + + // Create an editeng text selection in the first view. + EditView& rEditView = pView->GetTextEditOutlinerView()->GetEditView(); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + // 0th para, 0th char -> 0th para, 1st char. + ESelection aWordSelection(0, 0, 0, 1); + rEditView.SetSelection(aWordSelection); + + // Create a second view, and make sure that the new view sees the same + // cursor position as the old one. + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering({}); + ViewCallback aView2(SfxViewShell::Current()); + // Difference was 935 twips, the new view didn't see the editeng cursor of + // the old one. The new difference should be <1px, but here we deal with twips. + CPPUNIT_ASSERT(std::abs(aView1.m_aOwnCursor.Top() - aView2.m_aViewCursor.Top()) < 10); + // This was false, editeng text selection of the first view wasn't noticed + // by the second view. + CPPUNIT_ASSERT(aView2.m_bViewSelectionSet); + // This was false, the new view wasn't aware of the shape text lock created + // by the old view. + CPPUNIT_ASSERT(aView2.m_bViewLock); +} + +void SwTiledRenderingTest::testTrackChanges() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + + // Turn on track changes, type "zzz" at the end, and move to the start. + uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); + xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + ViewCallback aView(pWrtShell->GetSfxViewShell()); + pWrtShell->EndOfSection(); + pWrtShell->Insert("zzz"); + pWrtShell->StartOfSection(); + + // Get the redline just created + const SwRedlineTable& rTable = pWrtShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size()); + SwRangeRedline* pRedline = rTable[0]; + + // Reject the change by id, while the cursor does not cover the tracked change. + uno::Sequence<beans::PropertyValue> aPropertyValues(comphelper::InitPropertySequence( + { + {"RejectTrackedChange", uno::makeAny(static_cast<sal_uInt16>(pRedline->GetId()))} + })); + comphelper::dispatchCommand(".uno:RejectTrackedChange", aPropertyValues); + Scheduler::ProcessEventsToIdle(); + + // Assert that the reject was performed. + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // This was 'Aaa bbb.zzz', the change wasn't rejected. + CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb."), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); +} + +void SwTiledRenderingTest::testTrackChangesCallback() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Turn on track changes and type "x". + uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); + xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + m_nRedlineTableSizeChanged = 0; + pWrtShell->Insert("x"); + + // Assert that we get exactly one notification about the redline insert. + // This was 0, as LOK_CALLBACK_REDLINE_TABLE_SIZE_CHANGED wasn't sent. + CPPUNIT_ASSERT_EQUAL(1, m_nRedlineTableSizeChanged); + + CPPUNIT_ASSERT_EQUAL(-1, m_nTrackedChangeIndex); + pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + SfxItemSet aSet(pWrtShell->GetDoc()->GetAttrPool(), svl::Items<FN_REDLINE_ACCEPT_DIRECT, FN_REDLINE_ACCEPT_DIRECT>{}); + SfxVoidItem aItem(FN_REDLINE_ACCEPT_DIRECT); + aSet.Put(aItem); + pWrtShell->GetView().GetState(aSet); + // This failed, LOK_CALLBACK_STATE_CHANGED wasn't sent. + CPPUNIT_ASSERT_EQUAL(0, m_nTrackedChangeIndex); +} + +void SwTiledRenderingTest::testRedlineUpdateCallback() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Turn on track changes, type "xx" and delete the second one. + uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); + xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + pWrtShell->Insert("xx"); + m_nRedlineTableEntryModified = 0; + pWrtShell->DelLeft(); + + // Assert that we get exactly one notification about the redline update. + // This was 0, as LOK_CALLBACK_REDLINE_TABLE_ENTRY_MODIFIED wasn't sent. + CPPUNIT_ASSERT_EQUAL(1, m_nRedlineTableEntryModified); + + // Turn off the change tracking mode, make some modification to left of the + // redline so that its position changes + xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(false)); + pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + pWrtShell->Insert("This text is left of the redline"); + + // Position of the redline has changed => Modify callback + CPPUNIT_ASSERT_EQUAL(2, m_nRedlineTableEntryModified); + + pWrtShell->DelLeft(); + // Deletion also emits Modify callback + CPPUNIT_ASSERT_EQUAL(3, m_nRedlineTableEntryModified); + + // Make changes to the right of the redline => no position change in redline + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 100/*Go enough right */, /*bBasicCall=*/false); + pWrtShell->Insert("This text is right of the redline"); + + // No Modify callbacks + CPPUNIT_ASSERT_EQUAL(3, m_nRedlineTableEntryModified); +} + +void SwTiledRenderingTest::testSetViewGraphicSelection() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("frame.odt"); + int nView1 = SfxLokHelper::getView(); + ViewCallback aView1(SfxViewShell::Current()); + // Create a second view, and switch back to the first view. + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering({}); + SfxLokHelper::setView(nView1); + + // Mark the textframe in the first view. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + pView->MarkObj(pObject, pView->GetSdrPageView()); + CPPUNIT_ASSERT(aView1.m_bGraphicSelection); + + // Now start to switch to the second view (part of setView()). + pWrtShell->ShellLoseFocus(); + // This failed, mark handles were hidden in the first view. + CPPUNIT_ASSERT(!pView->areMarkHandlesHidden()); +} + +void SwTiledRenderingTest::testCreateViewGraphicSelection() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("frame.odt"); + ViewCallback aView1(SfxViewShell::Current()); + + // Mark the textframe in the first view. + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SdrPage* pPage = pWrtShell->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell->GetDrawView(); + aView1.m_bGraphicSelection = true; + pView->MarkObj(pObject, pView->GetSdrPageView()); + pWrtShell->HideCursor(); + CPPUNIT_ASSERT(aView1.m_bGraphicSelection); + + // Create a second view. + SfxLokHelper::createView(); + // This was false, creating a second view cleared the selection of the + // first one. + CPPUNIT_ASSERT(aView1.m_bGraphicSelection); + + // Make sure that the hidden text cursor isn't visible in the second view, either. + ViewCallback aView2(SfxViewShell::Current(), + [](ViewCallback& rView) { rView.m_bViewCursorVisible = true; }); + // This was true, the second view didn't get the visibility of the text + // cursor of the first view. + CPPUNIT_ASSERT(!aView2.m_bViewCursorVisible); + // This was false, the second view didn't get the graphic selection of the + // first view. + CPPUNIT_ASSERT(aView2.m_bGraphicViewSelection); +} + +void SwTiledRenderingTest::testCreateViewTextSelection() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + + // Create a text selection: + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + // Move the cursor into the second word. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 5, /*bBasicCall=*/false); + // Create a selection on the word. + pWrtShell->SelWrd(); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + // Did we indeed manage to select the second word? + CPPUNIT_ASSERT_EQUAL(OUString("bbb"), pShellCursor->GetText()); + + // Create a second view. + SfxLokHelper::createView(); + + // Make sure that the text selection is visible in the second view. + ViewCallback aView2(SfxViewShell::Current()); + // This failed, the second view didn't get the text selection of the first view. + CPPUNIT_ASSERT(!aView2.m_aViewSelection.isEmpty()); +} + +void SwTiledRenderingTest::testRedlineColors() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + + // Turn on track changes, type "zzz" at the end. + uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); + xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->EndOfSection(); + pWrtShell->Insert("zzz"); + + // Assert that info about exactly one author is returned. + OUString aInfo = pXTextDocument->getTrackedChangeAuthors(); + std::stringstream aStream(aInfo.toUtf8().getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("authors").size()); +} + +void SwTiledRenderingTest::testCommentEndTextEdit() +{ + // Create a document, type a character and remember the cursor position. + SwXTextDocument* pXTextDocument = createDoc(); + ViewCallback aView1(SfxViewShell::Current()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + tools::Rectangle aBodyCursor = aView1.m_aOwnCursor; + + // Create a comment and type a character there as well. + const int nCtrlAltC = KEY_MOD1 + KEY_MOD2 + 512 + 'c' - 'a'; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', nCtrlAltC); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', nCtrlAltC); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + // End comment text edit by clicking in the body text area, and assert that + // no unexpected cursor callbacks are emitted at origin (top left corner of + // the document). + aView1.m_bOwnCursorAtOrigin = false; + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aBodyCursor.getX(), aBodyCursor.getY(), 1, MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aBodyCursor.getX(), aBodyCursor.getY(), 1, MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + // This failed, the cursor was at 0, 0 at some point during end text edit + // of the comment. + CPPUNIT_ASSERT(!aView1.m_bOwnCursorAtOrigin); + + // Hit enter and expect invalidation. + Scheduler::ProcessEventsToIdle(); + aView1.m_bTilesInvalidated = false; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RETURN); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(aView1.m_bTilesInvalidated); +} + +void SwTiledRenderingTest::testCommentInsert() +{ + // Load a document with an as-char image in it. + comphelper::LibreOfficeKit::setTiledAnnotations(false); + SwXTextDocument* pXTextDocument = createDoc("image-comment.odt"); + SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); + SwView* pView = pDoc->GetDocShell()->GetView(); + + // Select the image. + pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); + // Make sure SwTextShell is replaced with SwDrawShell right now, not after 120 ms, as set in the + // SwView ctor. + pView->StopShellTimer(); + + // Add a comment. + uno::Reference<frame::XFrame> xFrame = pView->GetViewFrame()->GetFrame().GetFrameInterface(); + uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence( + { + {"Text", uno::makeAny(OUString("some text"))}, + {"Author", uno::makeAny(OUString("me"))}, + }); + ViewCallback aView(SfxViewShell::Current()); + comphelper::dispatchCommand(".uno:InsertAnnotation", xFrame, aPropertyValues); + Scheduler::ProcessEventsToIdle(); + OString aAnchorPos(aView.m_aComment.get_child("anchorPos").get_value<std::string>().c_str()); + // Without the accompanying fix in place, this test would have failed with + // - Expected: 1418, 1418, 0, 0 + // - Actual : 1418, 1418, 1024, 1024 + // i.e. the anchor position was a non-empty rectangle. + CPPUNIT_ASSERT_EQUAL(OString("1418, 1418, 0, 0"), aAnchorPos); + comphelper::LibreOfficeKit::setTiledAnnotations(true); +} + +void SwTiledRenderingTest::testCursorPosition() +{ + // Load a document and register a callback, should get an own cursor. + SwXTextDocument* pXTextDocument = createDoc(); + ViewCallback aView1(SfxViewShell::Current()); + + // Crete a second view, so the first view gets a collaborative cursor. + SfxLokHelper::createView(); + pXTextDocument->initializeForTiledRendering({}); + ViewCallback aView2(SfxViewShell::Current()); + + // Make sure the two are exactly the same. + // This failed, own cursor was at '1418, 1418', collaborative cursor was at + // '1425, 1425', due to pixel alignment. + CPPUNIT_ASSERT_EQUAL(aView1.m_aOwnCursor.toString(), aView1.m_aViewCursor.toString()); +} + +void SwTiledRenderingTest::testPaintCallbacks() +{ + // Test that paintTile() never results in callbacks, which can cause a + // paint <-> invalidate loop. + + // Load a document and register a callback for the first view. + SwXTextDocument* pXTextDocument = createDoc(); + ViewCallback aView1(SfxViewShell::Current()); + + // Create a second view and paint a tile on that second view. + SfxLokHelper::createView(); + int nCanvasWidth = 256; + int nCanvasHeight = 256; + std::vector<unsigned char> aBuffer(nCanvasWidth * nCanvasHeight * 4); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), Fraction(1.0), Point(), aBuffer.data()); + // Make sure that painting a tile in the second view doesn't invoke + // callbacks on the first view. + aView1.m_bCalled = false; + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, /*nTilePosY=*/0, /*nTileWidth=*/3840, /*nTileHeight=*/3840); + CPPUNIT_ASSERT(!aView1.m_bCalled); +} + +void SwTiledRenderingTest::testUndoRepairResult() +{ + // Load a document and create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + TestResultListener* pResult2 = new TestResultListener(); + css::uno::Reference< css::frame::XDispatchResultListener > xListener(static_cast< css::frame::XDispatchResultListener* >(pResult2), css::uno::UNO_QUERY); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + int nView2 = SfxLokHelper::getView(); + + // Insert a character in the second view. + SfxLokHelper::setView(nView2); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'b', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'b', 0); + Scheduler::ProcessEventsToIdle(); + + // Insert a character in the first view. + SfxLokHelper::setView(nView1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'a', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'a', 0); + Scheduler::ProcessEventsToIdle(); + + // Assert that by default the second view can't undo the action. + SfxLokHelper::setView(nView2); + comphelper::dispatchCommand(".uno:Undo", {}, xListener); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pResult2->m_nDocRepair); + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +void SwTiledRenderingTest::testRedoRepairResult() +{ + // Load a document and create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + TestResultListener* pResult2 = new TestResultListener(); + css::uno::Reference< css::frame::XDispatchResultListener > xListener(static_cast< css::frame::XDispatchResultListener* >(pResult2), css::uno::UNO_QUERY); + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + int nView2 = SfxLokHelper::getView(); + + // Insert a character in the second view. + SfxLokHelper::setView(nView2); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'b', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'b', 0); + Scheduler::ProcessEventsToIdle(); + + // Insert a character in the first view. + SfxLokHelper::setView(nView1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'a', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'a', 0); + Scheduler::ProcessEventsToIdle(); + + comphelper::dispatchCommand(".uno:Undo", {}, xListener); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(0), pResult2->m_nDocRepair); + + // Assert that by default the second view can't redo the action. + SfxLokHelper::setView(nView2); + comphelper::dispatchCommand(".uno:Redo", {}, xListener); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pResult2->m_nDocRepair); + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +namespace { + +void checkUndoRepairStates(SwXTextDocument* pXTextDocument, SwView* pView1, SwView* pView2) +{ + SfxItemSet aItemSet1(pXTextDocument->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items<SID_UNDO, SID_UNDO>{}); + SfxItemSet aItemSet2(pXTextDocument->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items<SID_UNDO, SID_UNDO>{}); + // first view, undo enabled + pView1->GetState(aItemSet1); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, aItemSet1.GetItemState(SID_UNDO)); + const SfxUInt32Item *pUnsetItem = dynamic_cast<const SfxUInt32Item*>(aItemSet1.GetItem(SID_UNDO)); + CPPUNIT_ASSERT(!pUnsetItem); + // second view, undo conflict + pView2->GetState(aItemSet2); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, aItemSet2.GetItemState(SID_UNDO)); + const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(aItemSet2.GetItem(SID_UNDO)); + CPPUNIT_ASSERT(pUInt32Item); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue()); +}; + +} + +void SwTiledRenderingTest::testDisableUndoRepair() +{ + // Create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + SwView* pView1 = dynamic_cast<SwView*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pView1); + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + ViewCallback aView2(SfxViewShell::Current()); + SwView* pView2 = dynamic_cast<SwView*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pView2); + int nView2 = SfxLokHelper::getView(); + + { + SfxItemSet aItemSet1(pXTextDocument->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items<SID_UNDO, SID_UNDO>{}); + SfxItemSet aItemSet2(pXTextDocument->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items<SID_UNDO, SID_UNDO>{}); + pView1->GetState(aItemSet1); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED, aItemSet1.GetItemState(SID_UNDO)); + pView2->GetState(aItemSet2); + CPPUNIT_ASSERT_EQUAL(SfxItemState::DISABLED, aItemSet2.GetItemState(SID_UNDO)); + } + + // Insert a character in the first view. + SfxLokHelper::setView(nView1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'k', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'k', 0); + Scheduler::ProcessEventsToIdle(); + checkUndoRepairStates(pXTextDocument, pView1, pView2); + + // Insert a character in the second view. + SfxLokHelper::setView(nView2); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'u', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'u', 0); + Scheduler::ProcessEventsToIdle(); + { + SfxItemSet aItemSet1(pXTextDocument->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items<SID_UNDO, SID_UNDO>{}); + SfxItemSet aItemSet2(pXTextDocument->GetDocShell()->GetDoc()->GetAttrPool(), svl::Items<SID_UNDO, SID_UNDO>{}); + // second view, undo enabled + pView2->GetState(aItemSet2); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, aItemSet2.GetItemState(SID_UNDO)); + const SfxUInt32Item *pUnsetItem = dynamic_cast<const SfxUInt32Item*>(aItemSet2.GetItem(SID_UNDO)); + CPPUNIT_ASSERT(!pUnsetItem); + // first view, undo conflict + pView1->GetState(aItemSet1); + CPPUNIT_ASSERT_EQUAL(SfxItemState::SET, aItemSet1.GetItemState(SID_UNDO)); + const SfxUInt32Item* pUInt32Item = dynamic_cast<const SfxUInt32Item*>(aItemSet1.GetItem(SID_UNDO)); + CPPUNIT_ASSERT(pUInt32Item); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), pUInt32Item->GetValue()); + } + + // Insert a character in the first view. + SfxLokHelper::setView(nView1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'l', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'l', 0); + Scheduler::ProcessEventsToIdle(); + checkUndoRepairStates(pXTextDocument, pView1, pView2); +} + +void SwTiledRenderingTest::testAllTrackedChanges() +{ + // Load a document. + createDoc("dummy.fodt"); + + uno::Reference<beans::XPropertySet> xPropSet(mxComponent, uno::UNO_QUERY); + xPropSet->setPropertyValue("RecordChanges", uno::makeAny(true)); + + // view #1 + SwView* pView1 = dynamic_cast<SwView*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pView1); + SwWrtShell* pWrtShell1 = pView1->GetWrtShellPtr(); + + // view #2 + int nView1 = SfxLokHelper::getView(); + int nView2 = SfxLokHelper::createView(); + SwView* pView2 = dynamic_cast<SwView*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pView2 && pView1 != pView2); + SwWrtShell* pWrtShell2 = pView2->GetWrtShellPtr(); + // Insert text and reject all + { + pWrtShell1->StartOfSection(); + pWrtShell1->Insert("hxx"); + + pWrtShell2->EndOfSection(); + pWrtShell2->Insert("cxx"); + } + + // Get the redline + const SwRedlineTable& rTable = pWrtShell2->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), rTable.size()); + { + SfxVoidItem aItem(FN_REDLINE_REJECT_ALL); + pView1->GetViewFrame()->GetDispatcher()->ExecuteList(FN_REDLINE_REJECT_ALL, + SfxCallMode::SYNCHRON, { &aItem }); + } + + // The reject all was performed. + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), rTable.size()); + { + SwShellCursor* pShellCursor = pWrtShell1->getShellCursor(false); + CPPUNIT_ASSERT_EQUAL(OUString("Aaa bbb."), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); + } + + // Insert text and accept all + { + pWrtShell1->StartOfSection(); + pWrtShell1->Insert("hyy"); + + pWrtShell2->EndOfSection(); + pWrtShell2->Insert("cyy"); + } + + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(2), rTable.size()); + { + SfxVoidItem aItem(FN_REDLINE_ACCEPT_ALL); + pView1->GetViewFrame()->GetDispatcher()->ExecuteList(FN_REDLINE_ACCEPT_ALL, + SfxCallMode::SYNCHRON, { &aItem }); + } + + // The accept all was performed + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(0), rTable.size()); + { + SwShellCursor* pShellCursor = pWrtShell2->getShellCursor(false); + CPPUNIT_ASSERT_EQUAL(OUString("hyyAaa bbb.cyy"), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); + } + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +void SwTiledRenderingTest::testDocumentRepair() +{ + // Create two views. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + // view #1 + SfxViewShell* pView1 = SfxViewShell::Current(); + + // view #2 + int nView1 = SfxLokHelper::getView(); + SfxLokHelper::createView(); + SfxViewShell* pView2 = SfxViewShell::Current(); + int nView2 = SfxLokHelper::getView(); + CPPUNIT_ASSERT(pView1 != pView2); + { + std::unique_ptr<SfxPoolItem> xItem1; + std::unique_ptr<SfxPoolItem> xItem2; + pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem1); + pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2); + const SfxBoolItem* pItem1 = dynamic_cast<const SfxBoolItem*>(xItem1.get()); + const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get()); + CPPUNIT_ASSERT(pItem1); + CPPUNIT_ASSERT(pItem2); + CPPUNIT_ASSERT_EQUAL(false, pItem1->GetValue()); + CPPUNIT_ASSERT_EQUAL(false, pItem2->GetValue()); + } + + // Insert a character in the second view. + SfxLokHelper::setView(nView2); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'u', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'u', 0); + Scheduler::ProcessEventsToIdle(); + { + std::unique_ptr<SfxPoolItem> xItem1; + std::unique_ptr<SfxPoolItem> xItem2; + pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem1); + pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, xItem2); + const SfxBoolItem* pItem1 = dynamic_cast<const SfxBoolItem*>(xItem1.get()); + const SfxBoolItem* pItem2 = dynamic_cast<const SfxBoolItem*>(xItem2.get()); + CPPUNIT_ASSERT(pItem1); + CPPUNIT_ASSERT(pItem2); + CPPUNIT_ASSERT_EQUAL(true, pItem1->GetValue()); + CPPUNIT_ASSERT_EQUAL(true, pItem2->GetValue()); + } + + SfxLokHelper::setView(nView1); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + SfxLokHelper::setView(nView2); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(nullptr, nullptr); +} + +namespace { + +void checkPageHeaderOrFooter(const SfxViewShell* pViewShell, sal_uInt16 nWhich, bool bValue) +{ + uno::Sequence<OUString> aSeq; + const SfxPoolItem* pState = nullptr; + pViewShell->GetDispatcher()->QueryState(nWhich, pState); + const SfxStringListItem* pListItem = dynamic_cast<const SfxStringListItem*>(pState); + CPPUNIT_ASSERT(pListItem); + pListItem->GetStringList(aSeq); + if (bValue) + { + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aSeq.getLength()); + CPPUNIT_ASSERT_EQUAL(OUString("Default Page Style"), aSeq[0]); + } + else + CPPUNIT_ASSERT(!aSeq.hasElements()); +}; + +} + +void SwTiledRenderingTest::testPageHeader() +{ + createDoc("dummy.fodt"); + SfxViewShell* pViewShell = SfxViewShell::Current(); + // Check Page Header State + checkPageHeaderOrFooter(pViewShell, FN_INSERT_PAGEHEADER, false); + // Insert Page Header + { + SfxStringItem aStyle(FN_INSERT_PAGEHEADER, "Default Page Style"); + SfxBoolItem aItem(FN_PARAM_1, true); + pViewShell->GetDispatcher()->ExecuteList(FN_INSERT_PAGEHEADER, SfxCallMode::API | SfxCallMode::SYNCHRON, {&aStyle, &aItem}); + } + // Check Page Header State + checkPageHeaderOrFooter(pViewShell, FN_INSERT_PAGEHEADER, true); + + // Remove Page Header + { + SfxStringItem aStyle(FN_INSERT_PAGEHEADER, "Default Page Style"); + SfxBoolItem aItem(FN_PARAM_1, false); + pViewShell->GetDispatcher()->ExecuteList(FN_INSERT_PAGEHEADER, SfxCallMode::API | SfxCallMode::SYNCHRON, {&aStyle, &aItem}); + } + // Check Page Header State + checkPageHeaderOrFooter(pViewShell, FN_INSERT_PAGEHEADER, false); +} + +void SwTiledRenderingTest::testPageFooter() +{ + createDoc("dummy.fodt"); + SfxViewShell* pViewShell = SfxViewShell::Current(); + // Check Page Footer State + checkPageHeaderOrFooter(pViewShell, FN_INSERT_PAGEFOOTER, false); + // Insert Page Footer + { + SfxStringItem aPageStyle(FN_INSERT_PAGEFOOTER, "Default Page Style"); + SfxBoolItem aItem(FN_PARAM_1, true); + pViewShell->GetDispatcher()->ExecuteList(FN_INSERT_PAGEFOOTER, SfxCallMode::API | SfxCallMode::SYNCHRON, {&aPageStyle, &aItem}); + } + // Check Page Footer State + checkPageHeaderOrFooter(pViewShell, FN_INSERT_PAGEFOOTER, true); + + // Remove Page Footer + { + SfxStringItem aPageStyle(FN_INSERT_PAGEFOOTER, "Default Page Style"); + SfxBoolItem aItem(FN_PARAM_1, false); + pViewShell->GetDispatcher()->ExecuteList(FN_INSERT_PAGEFOOTER, SfxCallMode::API | SfxCallMode::SYNCHRON, {&aPageStyle, &aItem}); + } + // Check Footer State + checkPageHeaderOrFooter(pViewShell, FN_INSERT_PAGEFOOTER, false); +} + +void SwTiledRenderingTest::testTdf115088() +{ + // We have three lines in the test document and we try to copy the second and third line + // To the beginning of the document + SwXTextDocument* pXTextDocument = createDoc("tdf115088.odt"); + + // Select and copy second and third line + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_HOME | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_HOME | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN | KEY_SHIFT); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN | KEY_SHIFT); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RIGHT | KEY_SHIFT); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RIGHT | KEY_SHIFT); + Scheduler::ProcessEventsToIdle(); + comphelper::dispatchCommand(".uno:Copy", uno::Sequence<beans::PropertyValue>()); + + // Move cursor to the beginning of the first line and paste + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_HOME | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_HOME | KEY_MOD1); + Scheduler::ProcessEventsToIdle(); + comphelper::dispatchCommand(".uno:PasteUnformatted", uno::Sequence<beans::PropertyValue>()); + Scheduler::ProcessEventsToIdle(); + + // Check the resulting text in the document. (it was 1Text\n1\n1\n1) + CPPUNIT_ASSERT_EQUAL(OUString("1\n1Text\n1\n1"), pXTextDocument->getText()->getString()); + + mxComponent->dispose(); + mxComponent.clear(); + comphelper::LibreOfficeKit::setActive(false); +} + +void SwTiledRenderingTest::testRedlineField() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + + // Turn on track changes and type "x". + uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY); + xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true)); + + SwDateTimeField aDate(static_cast<SwDateTimeFieldType*>(pWrtShell->GetFieldType(0, SwFieldIds::DateTime))); + //aDate->SetDateTime(::DateTime(::DateTime::SYSTEM)); + pWrtShell->Insert(aDate); + + // Get the redline just created + const SwRedlineTable& rTable = pWrtShell->GetDoc()->getIDocumentRedlineAccess().GetRedlineTable(); + CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), rTable.size()); + SwRangeRedline* pRedline = rTable[0]; + CPPUNIT_ASSERT(pRedline->GetDescr().indexOf(aDate.GetFieldName())!= -1); +} + +void SwTiledRenderingTest::testIMESupport() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + VclPtr<vcl::Window> pDocWindow = pXTextDocument->getDocWindow(); + + SwView* pView = dynamic_cast<SwView*>(SfxViewShell::Current()); + assert(pView); + SwWrtShell* pWrtShell = pView->GetWrtShellPtr(); + + // sequence of chinese IME compositions when 'nihao' is typed in an IME + const std::vector<OString> aUtf8Inputs{ "年", "你", "你好", "你哈", "你好", "你好" }; + std::vector<OUString> aInputs; + std::transform(aUtf8Inputs.begin(), aUtf8Inputs.end(), + std::back_inserter(aInputs), [](OString aInput) { + return OUString::fromUtf8(aInput); + }); + for (const auto& aInput: aInputs) + { + pDocWindow->PostExtTextInputEvent(VclEventId::ExtTextInput, aInput); + } + pDocWindow->PostExtTextInputEvent(VclEventId::EndExtTextInput, ""); + + // the cursor should be at position 2nd + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), pShellCursor->GetPoint()->nContent.GetIndex()); + + // content contains only the last IME composition, not all + CPPUNIT_ASSERT_EQUAL(aInputs[aInputs.size() - 1].concat("Aaa bbb."), pShellCursor->GetPoint()->nNode.GetNode().GetTextNode()->GetText()); +} + +void SwTiledRenderingTest::testSplitNodeRedlineCallback() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("splitnode_redline_callback.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // 1. test case + // Move cursor between the two tracked changes + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + Scheduler::ProcessEventsToIdle(); + + // Add a new line + m_nRedlineTableEntryModified = 0; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RETURN); + Scheduler::ProcessEventsToIdle(); + + // Assert that we get a notification about redline modification + // The redline after the inserted node gets a different vertical position + CPPUNIT_ASSERT_EQUAL(1, m_nRedlineTableEntryModified); + + // 2. test case + // Move cursor back to the first line, so adding new line will affect both tracked changes + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_HOME | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_HOME | KEY_MOD1); + Scheduler::ProcessEventsToIdle(); + + // Add a new line + m_nRedlineTableEntryModified = 0; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RETURN); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(2, m_nRedlineTableEntryModified); + + // 3. test case + // Move cursor to the end of the document, so adding a new line won't affect any tracked changes + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_END | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_END | KEY_MOD1); + Scheduler::ProcessEventsToIdle(); + + // Add a new line + m_nRedlineTableEntryModified = 0; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RETURN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RETURN); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(0, m_nRedlineTableEntryModified); +} + +void SwTiledRenderingTest::testDeleteNodeRedlineCallback() +{ + // Load a document. + SwXTextDocument* pXTextDocument = createDoc("removenode_redline_callback.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // 1. test case + // Move cursor between the two tracked changes + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DOWN); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DOWN); + Scheduler::ProcessEventsToIdle(); + + // Remove one (empty) line + m_nRedlineTableEntryModified = 0; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DELETE); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DELETE); + Scheduler::ProcessEventsToIdle(); + + // Assert that we get a notification about redline modification + // The redline after the removed node gets a different vertical position + CPPUNIT_ASSERT_EQUAL(1, m_nRedlineTableEntryModified); + + // 2. test case + // Move cursor back to the first line, so removing one line will affect both tracked changes + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_HOME | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_HOME | KEY_MOD1); + Scheduler::ProcessEventsToIdle(); + + // Remove a new line + m_nRedlineTableEntryModified = 0; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_DELETE); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_DELETE); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(2, m_nRedlineTableEntryModified); + + // 3. test case + // Move cursor to the end of the document, so removing one line won't affect any tracked changes + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_END | KEY_MOD1); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_END | KEY_MOD1); + Scheduler::ProcessEventsToIdle(); + + // Remove a line + m_nRedlineTableEntryModified = 0; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_BACKSPACE); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_BACKSPACE); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(0, m_nRedlineTableEntryModified); +} + + +void SwTiledRenderingTest::testVisCursorInvalidation() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + ViewCallback aView1(SfxViewShell::Current()); + int nView1 = SfxLokHelper::getView(); + + SfxLokHelper::createView(); + int nView2 = SfxLokHelper::getView(); + ViewCallback aView2(SfxViewShell::Current()); + Scheduler::ProcessEventsToIdle(); + + + // Move visible cursor in the first view + SfxLokHelper::setView(nView1); + Scheduler::ProcessEventsToIdle(); + + aView1.m_bOwnCursorInvalidated = false; + aView1.m_bViewCursorInvalidated = false; + aView2.m_bOwnCursorInvalidated = false; + aView2.m_bViewCursorInvalidated = false; + + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_RIGHT); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, KEY_RIGHT); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT(!aView1.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(!aView2.m_bOwnCursorInvalidated); + + // Insert text in the second view which moves the other view's cursor too + SfxLokHelper::setView(nView2); + + aView1.m_bOwnCursorInvalidated = false; + aView1.m_bViewCursorInvalidated = false; + aView2.m_bOwnCursorInvalidated = false; + aView2.m_bViewCursorInvalidated = false; + + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated); + + // Do the same as before, but set the related compatibility flag first + SfxLokHelper::setView(nView2); + + comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(true); + + aView1.m_bOwnCursorInvalidated = false; + aView1.m_bViewCursorInvalidated = false; + aView2.m_bOwnCursorInvalidated = false; + aView2.m_bViewCursorInvalidated = false; + + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView1.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT_EQUAL(nView2, aView1.m_nOwnCursorInvalidatedBy); + CPPUNIT_ASSERT(aView2.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT_EQUAL(nView2, aView2.m_nOwnCursorInvalidatedBy); + + comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(false); +} + +void SwTiledRenderingTest::testDeselectCustomShape() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + Point aStart = pShellCursor->GetSttPos(); + aStart.setX(aStart.getX() - 1000); + aStart.setY(aStart.getY() - 1000); + + comphelper::dispatchCommand(".uno:BasicShapes.hexagon", uno::Sequence<beans::PropertyValue>()); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pWrtShell->GetDrawView()->GetMarkedObjectList().GetMarkCount()); + + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aStart.getX(), aStart.getY(), 1, MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pWrtShell->GetDrawView()->GetMarkedObjectList().GetMarkCount()); +} + +void SwTiledRenderingTest::testSemiTransparent() +{ + // Load a document where the top left tile contains a semi-transparent rectangle shape. + SwXTextDocument* pXTextDocument = createDoc("semi-transparent.odt"); + + // Render a larger area, and then get the color of the bottom right corner of our tile. + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + size_t nTileSize = 256; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/15360, /*nTileHeight=*/7680); + pDevice->EnableMapMode(false); + Bitmap aBitmap = pDevice->GetBitmap(Point(0, 0), Size(nTileSize, nTileSize)); + Bitmap::ScopedReadAccess pAccess(aBitmap); + Color aColor(pAccess->GetPixel(255, 255)); + + // Without the accompanying fix in place, this test would have failed with 'Expected greater or + // equal than: 190; Actual: 159'. This means the semi-transparent gray rectangle was darker than + // expected, as it was painted twice. + CPPUNIT_ASSERT_GREATEREQUAL(190, static_cast<int>(aColor.R)); + CPPUNIT_ASSERT_GREATEREQUAL(190, static_cast<int>(aColor.G)); + CPPUNIT_ASSERT_GREATEREQUAL(190, static_cast<int>(aColor.B)); +} + +void SwTiledRenderingTest::testHighlightNumbering() +{ + // Load a document where the top left tile contains a semi-transparent rectangle shape. + SwXTextDocument* pXTextDocument = createDoc("tdf114799.docx"); + + // Render a larger area, and then get the color of the bottom right corner of our tile. + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + size_t nTileSize = 256; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/15360, /*nTileHeight=*/7680); + pDevice->EnableMapMode(false); + Bitmap aBitmap = pDevice->GetBitmap(Point(0, 0), Size(nTileSize, nTileSize)); + Bitmap::ScopedReadAccess pAccess(aBitmap); + + // Yellow highlighting over numbering + Color aColor(pAccess->GetPixel(103, 148)); + CPPUNIT_ASSERT_EQUAL(COL_YELLOW, aColor); +} + +void SwTiledRenderingTest::testClipText() +{ + // Load a document where the top left tile contains table text with + // too small line height, but with top and bottom paragraph margins, + // avoiding of clipping top and bottom parts of the characters. + SwXTextDocument* pXTextDocument = createDoc("tdf117448.fodt"); + + // Render a larger area, and then get the top and bottom of the text in that tile + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + size_t nTileSize = 256; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/15360, /*nTileHeight=*/7680); + pDevice->EnableMapMode(false); + Bitmap aBitmap = pDevice->GetBitmap(Point(0, 0), Size(nTileSize, nTileSize)); + Bitmap::ScopedReadAccess pAccess(aBitmap); + + // check top margin, it's not white completely (i.e. showing top of letter "T") + bool bClipTop = true; + for (int i = 0; i < 150; i++) + { + Color aTopTextColor(pAccess->GetPixel(98, 98 + i)); + if (aTopTextColor.R < 255) + { + bClipTop = false; + break; + } + } + CPPUNIT_ASSERT(!bClipTop); + // switch off because of false alarm on some platform, maybe related to font replacements +#if 0 + // check bottom margin, it's not white completely (i.e. showing bottom of letter "g") + bool bClipBottom = true; + for (int i = 0; i < 150; i++) + { + Color aBottomTextColor(pAccess->GetPixel(110, 98 + i)); + if (aBottomTextColor.R < 255) + { + bClipBottom = false; + break; + } + } + CPPUNIT_ASSERT(!bClipBottom); +#endif +} + +void SwTiledRenderingTest::testAnchorTypes() +{ + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); + SwView* pView = pXTextDocument->GetDocShell()->GetView(); + pView->GetViewFrame()->GetDispatcher()->Execute(FN_CNTNT_TO_NEXT_FRAME, SfxCallMode::SYNCHRON); + SfxItemSet aSet(pDoc->GetAttrPool(), svl::Items<FN_TOOL_ANCHOR_PAGE, FN_TOOL_ANCHOR_PAGE>{}); + SfxBoolItem aItem(FN_TOOL_ANCHOR_PAGE); + aSet.Put(aItem); + auto pShell = dynamic_cast<SwBaseShell*>(pView->GetCurShell()); + pShell->GetState(aSet); + // Without the accompanying fix in place, this test would have failed, setting the anchor type + // to other than as/at-char was possible. + CPPUNIT_ASSERT(!aSet.HasItem(FN_TOOL_ANCHOR_PAGE)); +} + +void SwTiledRenderingTest::testLanguageStatus() +{ + SwXTextDocument* pXTextDocument = createDoc("dummy.fodt"); + SwView* pView = pXTextDocument->GetDocShell()->GetView(); + std::unique_ptr<SfxPoolItem> pItem; + pView->GetViewFrame()->GetBindings().QueryState(SID_LANGUAGE_STATUS, pItem); + auto pStringListItem = dynamic_cast<SfxStringListItem*>(pItem.get()); + CPPUNIT_ASSERT(pStringListItem); + + uno::Sequence< OUString > aList; + pStringListItem->GetStringList(aList); + CPPUNIT_ASSERT_EQUAL(OUString("English (USA);en-US"), aList[0]); +} + +void SwTiledRenderingTest::testRedlineNotificationDuringSave() +{ + // Load a document with redlines which are hidden at a layout level. + // It's an empty document, just settings.xml and content.xml are custom. + SwXTextDocument* pXTextDocument = createDoc("redline-notification-during-save.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Save the document. + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer8"); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + // Without the accompanying fix in place, this test would have never returned due to an infinite + // loop while sending not needed LOK notifications for redline changes during save. + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); +} + +void SwTiledRenderingTest::testHyperlink() +{ + comphelper::LibreOfficeKit::setViewIdForVisCursorInvalidation(true); + SwXTextDocument* pXTextDocument = createDoc("hyperlink.odt"); + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + SwShellCursor* pShellCursor = pWrtShell->getShellCursor(false); + + Point aStart = pShellCursor->GetSttPos(); + aStart.setX(aStart.getX() + 1800); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONDOWN, aStart.getX(), aStart.getY(), 1, + MOUSE_LEFT, 0); + pXTextDocument->postMouseEvent(LOK_MOUSEEVENT_MOUSEBUTTONUP, aStart.getX(), aStart.getY(), 1, + MOUSE_LEFT, 0); + Scheduler::ProcessEventsToIdle(); + + CPPUNIT_ASSERT_EQUAL(OString("hyperlink"), m_sHyperlinkText); + CPPUNIT_ASSERT_EQUAL(OString("http://example.com/"), m_sHyperlinkLink); +} + +void SwTiledRenderingTest::testFieldmark() +{ + // Without the accompanying fix in place, this crashed on load. + createDoc("fieldmark.docx"); +} + +void SwTiledRenderingTest::testDropDownFormFieldButton() +{ + SwXTextDocument* pXTextDocument = createDoc("drop_down_form_field.odt"); + pXTextDocument->setClientVisibleArea(tools::Rectangle(0, 0, 10000, 4000)); + + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Move the cursor to trigger displaying of the field button. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + CPPUNIT_ASSERT(m_aFormFieldButton.isEmpty()); + + // Do a tile rendering to trigger the button message with a valid text area + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/10000, /*nTileHeight=*/4000); + + CPPUNIT_ASSERT(!m_aFormFieldButton.isEmpty()); + { + std::stringstream aStream(m_aFormFieldButton.getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + OString sAction = aTree.get_child("action").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("show"), sAction); + + OString sType = aTree.get_child("type").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("drop-down"), sType); + + OString sTextArea = aTree.get_child("textArea").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("1538, 1418, 1026, 275"), sTextArea); + + boost::property_tree::ptree aItems = aTree.get_child("params").get_child("items"); + CPPUNIT_ASSERT_EQUAL(size_t(6), aItems.size()); + + OStringBuffer aItemList; + for (auto &item : aItems) + { + aItemList.append(item.second.get_value<std::string>().c_str()); + aItemList.append(";"); + } + CPPUNIT_ASSERT_EQUAL(OString("2019/2020;2020/2021;2021/2022;2022/2023;2023/2024;2024/2025;"), aItemList.toString()); + + OString sSelected = aTree.get_child("params").get_child("selected").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("1"), sSelected); + + OString sPlaceholder = aTree.get_child("params").get_child("placeholderText").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("No Item specified"), sPlaceholder); + } + + // Move the cursor back so the button becomes hidden. + pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + + CPPUNIT_ASSERT(!m_aFormFieldButton.isEmpty()); + { + std::stringstream aStream(m_aFormFieldButton.getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + OString sAction = aTree.get_child("action").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("hide"), sAction); + + OString sType = aTree.get_child("type").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("drop-down"), sType); + } +} + +void SwTiledRenderingTest::testDropDownFormFieldButtonEditing() +{ + SwXTextDocument* pXTextDocument = createDoc("drop_down_form_field2.odt"); + pXTextDocument->setClientVisibleArea(tools::Rectangle(0, 0, 10000, 4000)); + + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Move the cursor to trigger displaying of the field button. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + CPPUNIT_ASSERT(m_aFormFieldButton.isEmpty()); + + // Do a tile rendering to trigger the button message with a valid text area + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/10000, /*nTileHeight=*/4000); + + // The item with the index '1' is selected by default + CPPUNIT_ASSERT(!m_aFormFieldButton.isEmpty()); + { + std::stringstream aStream(m_aFormFieldButton.getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + OString sSelected = aTree.get_child("params").get_child("selected").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("1"), sSelected); + } + m_aFormFieldButton = ""; + + // Trigger a form field event to select a different item. + vcl::ITiledRenderable::StringMap aArguments; + aArguments["type"] = "drop-down"; + aArguments["cmd"] = "selected"; + aArguments["data"] = "3"; + pXTextDocument->executeFromFieldEvent(aArguments); + + // Do a tile rendering to trigger the button message. + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/10000, /*nTileHeight=*/4000); + + CPPUNIT_ASSERT(!m_aFormFieldButton.isEmpty()); + { + std::stringstream aStream(m_aFormFieldButton.getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + OString sSelected = aTree.get_child("params").get_child("selected").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("3"), sSelected); + } +} + +void SwTiledRenderingTest::testDropDownFormFieldButtonNoSelection() +{ + SwXTextDocument* pXTextDocument = createDoc("drop_down_form_field_noselection.odt"); + pXTextDocument->setClientVisibleArea(tools::Rectangle(0, 0, 10000, 4000)); + + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Move the cursor to trigger displaying of the field button. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + CPPUNIT_ASSERT(m_aFormFieldButton.isEmpty()); + + // Do a tile rendering to trigger the button message with a valid text area + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/10000, /*nTileHeight=*/4000); + + // None of the items is selected + CPPUNIT_ASSERT(!m_aFormFieldButton.isEmpty()); + { + std::stringstream aStream(m_aFormFieldButton.getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + OString sSelected = aTree.get_child("params").get_child("selected").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("-1"), sSelected); + } +} + +void SwTiledRenderingTest::testDropDownFormFieldButtonNoItem() +{ + SwXTextDocument* pXTextDocument = createDoc("drop_down_form_field_noitem.odt"); + pXTextDocument->setClientVisibleArea(tools::Rectangle(0, 0, 10000, 4000)); + + SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell(); + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this); + + // Move the cursor to trigger displaying of the field button. + pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, /*bBasicCall=*/false); + CPPUNIT_ASSERT(m_aFormFieldButton.isEmpty()); + + // Do a tile rendering to trigger the button message with a valid text area + size_t nCanvasWidth = 1024; + size_t nCanvasHeight = 512; + std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0); + ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT); + pDevice->SetBackground(Wallpaper(COL_TRANSPARENT)); + pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight), + Fraction(1.0), Point(), aPixmap.data()); + pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, /*nTilePosX=*/0, + /*nTilePosY=*/0, /*nTileWidth=*/10000, /*nTileHeight=*/4000); + + // There is not item specified for the field + CPPUNIT_ASSERT(!m_aFormFieldButton.isEmpty()); + { + std::stringstream aStream(m_aFormFieldButton.getStr()); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + + boost::property_tree::ptree aItems = aTree.get_child("params").get_child("items"); + CPPUNIT_ASSERT_EQUAL(size_t(0), aItems.size()); + + OString sSelected = aTree.get_child("params").get_child("selected").get_value<std::string>().c_str(); + CPPUNIT_ASSERT_EQUAL(OString("-1"), sSelected); + } +} + +CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |