LCOV - code coverage report
Current view: top level - sw/qa/core - swdoc-test.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 375 377 99.5 %
Date: 2012-08-25 Functions: 29 30 96.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1023 2029 50.4 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * Version: MPL 1.1 / GPLv3+ / LGPLv3+
       4                 :            :  *
       5                 :            :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :            :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :            :  * the License. You may obtain a copy of the License at
       8                 :            :  * http://www.mozilla.org/MPL/
       9                 :            :  *
      10                 :            :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :            :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :            :  * for the specific language governing rights and limitations under the
      13                 :            :  * License.
      14                 :            :  *
      15                 :            :  * The Initial Developer of the Original Code is
      16                 :            :  *       Thorsten Behrens <tbehrens@novell.com>
      17                 :            :  * Portions created by the Initial Developer are Copyright (C) 2011 the
      18                 :            :  * Initial Developer. All Rights Reserved.
      19                 :            :  *
      20                 :            :  * Contributor(s):
      21                 :            :  *   Thorsten Behrens <tbehrens@novell.com>
      22                 :            :  *   Caolán McNamara <caolanm@redhat.com>
      23                 :            :  *
      24                 :            :  * Alternatively, the contents of this file may be used under the terms of
      25                 :            :  * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      26                 :            :  * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
      27                 :            :  * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
      28                 :            :  * instead of those above.
      29                 :            :  */
      30                 :            : 
      31                 :            : #include <sal/config.h>
      32                 :            : #include <test/bootstrapfixture.hxx>
      33                 :            : 
      34                 :            : #include <rtl/strbuf.hxx>
      35                 :            : #include <osl/file.hxx>
      36                 :            : 
      37                 :            : #include <tools/urlobj.hxx>
      38                 :            : #include <unotools/tempfile.hxx>
      39                 :            : 
      40                 :            : #include <editeng/langitem.hxx>
      41                 :            : #include <editeng/charhiddenitem.hxx>
      42                 :            : 
      43                 :            : #include <sfx2/app.hxx>
      44                 :            : #include <sfx2/docfilt.hxx>
      45                 :            : #include <sfx2/docfile.hxx>
      46                 :            : #include <sfx2/sfxmodelfactory.hxx>
      47                 :            : 
      48                 :            : #include "breakit.hxx"
      49                 :            : #include "doc.hxx"
      50                 :            : #include "docsh.hxx"
      51                 :            : #include "docstat.hxx"
      52                 :            : #include "docufld.hxx"
      53                 :            : #include "fmtanchr.hxx"
      54                 :            : #include "init.hxx"
      55                 :            : #include "ndtxt.hxx"
      56                 :            : #include "shellio.hxx"
      57                 :            : #include "shellres.hxx"
      58                 :            : #include "swcrsr.hxx"
      59                 :            : #include "swscanner.hxx"
      60                 :            : #include "swmodule.hxx"
      61                 :            : #include "swtypes.hxx"
      62                 :            : #include "fmtftn.hxx"
      63                 :            : #include "fmtrfmrk.hxx"
      64                 :            : #include "fmtfld.hxx"
      65                 :            : #include "redline.hxx"
      66                 :            : #include "docary.hxx"
      67                 :            : #include "modeltoviewhelper.hxx"
      68                 :            : #include "scriptinfo.hxx"
      69                 :            : 
      70                 :         60 : SO2_DECL_REF(SwDocShell)
      71 [ +  - ][ +  - ]:        144 : SO2_IMPL_REF(SwDocShell)
         [ -  + ][ +  + ]
         [ +  - ][ +  - ]
      72                 :            : 
      73                 :            : using namespace ::com::sun::star;
      74                 :            : 
      75                 :            : /* Implementation of Swdoc-Test class */
      76                 :            : 
      77 [ +  - ][ -  + ]:         72 : class SwDocTest : public test::BootstrapFixture
      78                 :            : {
      79                 :            : public:
      80                 :            :     virtual void setUp();
      81                 :            :     virtual void tearDown();
      82                 :            : 
      83                 :            :     void randomTest();
      84                 :            :     void testPageDescName();
      85                 :            :     void testFileNameFields();
      86                 :            :     void testDocStat();
      87                 :            :     void testModelToViewHelper();
      88                 :            :     void testSwScanner();
      89                 :            :     void testUserPerceivedCharCount();
      90                 :            :     void testGraphicAnchorDeletion();
      91                 :            : 
      92 [ +  - ][ +  - ]:          6 :     CPPUNIT_TEST_SUITE(SwDocTest);
         [ +  - ][ +  - ]
                 [ #  # ]
      93 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(randomTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      94 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPageDescName);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      95 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testFileNameFields);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      96 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testDocStat);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      97 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testModelToViewHelper);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      98 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testSwScanner);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      99 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testUserPerceivedCharCount);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     100 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testGraphicAnchorDeletion);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     101 [ +  - ][ +  - ]:          6 :     CPPUNIT_TEST_SUITE_END();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     102                 :            : 
     103                 :            : private:
     104                 :            :     SwDoc *m_pDoc;
     105                 :            :     SwDocShellRef m_xDocShRef;
     106                 :            : };
     107                 :            : 
     108                 :          3 : void SwDocTest::testPageDescName()
     109                 :            : {
     110         [ +  - ]:          3 :     ShellResource aShellResources;
     111                 :            : 
     112         [ +  - ]:          3 :     std::vector<rtl::OUString> aResults;
     113                 :            : 
     114                 :            :     //These names must be unique for each different combination, otherwise
     115                 :            :     //duplicate page description names may exist, which will causes lookup
     116                 :            :     //by name to be incorrect, and so the corresponding export to .odt
     117 [ +  - ][ +  - ]:          3 :     aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::NORMAL_PAGE));
         [ +  - ][ +  - ]
     118 [ +  - ][ +  - ]:          3 :     aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FIRST_PAGE));
         [ +  - ][ +  - ]
     119 [ +  - ][ +  - ]:          3 :     aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FOLLOW_PAGE));
         [ +  - ][ +  - ]
     120                 :            : 
     121         [ +  - ]:          3 :     std::sort(aResults.begin(), aResults.end());
     122 [ +  - ][ +  - ]:          3 :     aResults.erase(std::unique(aResults.begin(), aResults.end()), aResults.end());
     123                 :            : 
     124 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("GetPageDescName results must be unique", aResults.size() == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     125                 :          3 : }
     126                 :            : 
     127                 :            : //See https://bugs.freedesktop.org/show_bug.cgi?id=32463
     128                 :          3 : void SwDocTest::testFileNameFields()
     129                 :            : {
     130                 :            :     //Here's a file name with some chars in it that will be %% encoded, when expanding
     131                 :            :     //SwFileNameFields we want to restore the original readable filename
     132 [ +  - ][ +  - ]:          3 :     utl::TempFile aTempFile(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("demo [name]")));
         [ +  - ][ +  - ]
     133                 :          3 :     aTempFile.EnableKillingFile();
     134                 :            : 
     135 [ +  - ][ +  - ]:          3 :     INetURLObject aTempFileURL(aTempFile.GetURL());
         [ +  - ][ +  - ]
     136 [ +  - ][ +  - ]:          3 :     String sFileURL = aTempFileURL.GetMainURL(INetURLObject::NO_DECODE);
     137         [ +  - ]:          3 :     SfxMedium aDstMed(sFileURL, STREAM_STD_READWRITE);
     138                 :            : 
     139                 :            :     SfxFilter aFilter(
     140                 :            :         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text")),
     141                 :            :         rtl::OUString(), 0, 0, rtl::OUString(), 0, rtl::OUString(),
     142 [ +  - ][ +  - ]:          3 :         rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TEXT")), rtl::OUString() );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     143         [ +  - ]:          3 :     aDstMed.SetFilter(&aFilter);
     144                 :            : 
     145         [ +  - ]:          3 :     m_xDocShRef->DoSaveAs(aDstMed);
     146         [ +  - ]:          3 :     m_xDocShRef->DoSaveCompleted(&aDstMed);
     147                 :            : 
     148         [ +  - ]:          3 :     const INetURLObject &rUrlObj = m_xDocShRef->GetMedium()->GetURLObject();
     149                 :            : 
     150         [ +  - ]:          3 :     SwFileNameFieldType aNameField(m_pDoc);
     151                 :            : 
     152                 :            :     {
     153 [ +  - ][ +  - ]:          3 :         rtl::OUString sResult(aNameField.Expand(FF_NAME));
                 [ +  - ]
     154                 :            :         rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
     155         [ +  - ]:          3 :             true,INetURLObject::DECODE_WITH_CHARSET));
     156 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     157                 :            :     }
     158                 :            : 
     159                 :            :     {
     160 [ +  - ][ +  - ]:          3 :         rtl::OUString sResult(aNameField.Expand(FF_PATHNAME));
                 [ +  - ]
     161         [ +  - ]:          3 :         rtl::OUString sExpected(rUrlObj.GetFull());
     162 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     163                 :            :     }
     164                 :            : 
     165                 :            :     {
     166 [ +  - ][ +  - ]:          3 :         rtl::OUString sResult(aNameField.Expand(FF_PATH));
                 [ +  - ]
     167         [ +  - ]:          3 :         INetURLObject aTemp(rUrlObj);
     168         [ +  - ]:          3 :         aTemp.removeSegment();
     169         [ +  - ]:          3 :         rtl::OUString sExpected(aTemp.PathToFileName());
     170 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     171                 :            :     }
     172                 :            : 
     173                 :            :     {
     174 [ +  - ][ +  - ]:          3 :         rtl::OUString sResult(aNameField.Expand(FF_NAME_NOEXT));
                 [ +  - ]
     175                 :            :         rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
     176         [ +  - ]:          3 :             true,INetURLObject::DECODE_WITH_CHARSET));
     177                 :            :         //Chop off .tmp
     178                 :          3 :         sExpected = sExpected.copy(0, sExpected.getLength() - 4);
     179 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     180                 :            :     }
     181                 :            : 
     182 [ +  - ][ +  - ]:          3 :     m_xDocShRef->DoInitNew(0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     183                 :          3 : }
     184                 :            : 
     185                 :            : //See http://lists.freedesktop.org/archives/libreoffice/2011-August/016666.html
     186                 :            : //Remove unnecessary parameter to IDocumentStatistics::UpdateDocStat for
     187                 :            : //motivation
     188                 :          3 : void SwDocTest::testDocStat()
     189                 :            : {
     190 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Expected initial 0 count", m_pDoc->GetDocStat().nChar == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     191                 :            : 
     192 [ +  - ][ +  - ]:          3 :     SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
     193         [ +  - ]:          3 :     SwPaM aPaM(aIdx);
     194                 :            : 
     195         [ +  - ]:          3 :     rtl::OUString sText(RTL_CONSTASCII_USTRINGPARAM("Hello World"));
     196 [ +  - ][ +  - ]:          3 :     m_pDoc->InsertString(aPaM, sText);
                 [ +  - ]
     197                 :            : 
     198 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Should still be non-updated 0 count", m_pDoc->GetDocStat().nChar == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     199                 :            : 
     200         [ +  - ]:          3 :     SwDocStat aDocStat = m_pDoc->GetUpdatedDocStat();
     201                 :          3 :     sal_uLong nLen = static_cast<sal_uLong>(sText.getLength());
     202                 :            : 
     203 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Should now have updated count", aDocStat.nChar == nLen);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     204                 :            : 
     205 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("And cache is updated too", m_pDoc->GetDocStat().nChar == nLen);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     206                 :          3 : }
     207                 :            : 
     208                 :            : //For UI character counts we should follow UAX#29 and display the user
     209                 :            : //perceived characters, not the number of codepoints, nor the number of code
     210                 :            : //units http://unicode.org/reports/tr29/
     211                 :          3 : void SwDocTest::testUserPerceivedCharCount()
     212                 :            : {
     213         [ +  - ]:          3 :     SwBreakIt *pBreakIter = SwBreakIt::Get();
     214                 :            : 
     215                 :            :     //Grapheme example, two different unicode code-points perceived by the user as a single
     216                 :            :     //glyph
     217                 :          3 :     const sal_Unicode ALEF_QAMATS [] = { 0x05D0, 0x05B8 };
     218                 :          3 :     ::rtl::OUString sALEF_QAMATS(ALEF_QAMATS, SAL_N_ELEMENTS(ALEF_QAMATS));
     219         [ +  - ]:          3 :     sal_Int32 nGraphemeCount = pBreakIter->getGraphemeCount(sALEF_QAMATS);
     220 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Grapheme Count should be 1", nGraphemeCount == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     221                 :            : 
     222                 :            :     //Surrogate pair example, one single unicode code-point (U+1D11E)
     223                 :            :     //represented as two code units in UTF-16
     224                 :          3 :     const sal_Unicode GCLEF[] = { 0xD834, 0xDD1E };
     225                 :          3 :     ::rtl::OUString sGCLEF(GCLEF, SAL_N_ELEMENTS(GCLEF));
     226         [ +  - ]:          3 :     sal_Int32 nCount = pBreakIter->getGraphemeCount(sGCLEF);
     227 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Surrogate Pair should be counted as single character", nCount == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     228                 :          3 : }
     229                 :            : 
     230                 :          3 : void SwDocTest::testModelToViewHelper()
     231                 :            : {
     232 [ +  - ][ +  - ]:          3 :     SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
     233         [ +  - ]:          3 :     SwPaM aPaM(aIdx);
     234                 :            : 
     235                 :            :     {
     236         [ +  - ]:          3 :         SwFmtFtn aFtn;
     237 [ +  - ][ +  - ]:          3 :         aFtn.SetNumStr(rtl::OUString("foo"));
                 [ +  - ]
     238                 :            : 
     239         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     240 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString("AAAAA BBBBB "));
                 [ +  - ]
     241                 :          3 :         SwTxtNode* pTxtNode = aPaM.GetNode()->GetTxtNode();
     242                 :          3 :         xub_StrLen nPos = aPaM.GetPoint()->nContent.GetIndex();
     243         [ +  - ]:          3 :         pTxtNode->InsertItem(aFtn, nPos, nPos);
     244 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString(" CCCCC "));
                 [ +  - ]
     245                 :          3 :         nPos = aPaM.GetPoint()->nContent.GetIndex();
     246         [ +  - ]:          3 :         pTxtNode->InsertItem(aFtn, nPos, nPos);
     247 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString(" DDDDD"));
                 [ +  - ]
     248 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pTxtNode->GetTxt().Len() == (4*5) + 5 + 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     249                 :            : 
     250                 :            :         //set start of selection to first B
     251 [ +  - ][ +  - ]:          3 :         aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 6);
     252         [ +  - ]:          3 :         aPaM.SetMark();
     253                 :            :         //set end of selection to last C
     254 [ +  - ][ +  - ]:          3 :         aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 14);
     255                 :            :         //set character attribute hidden on range
     256         [ +  - ]:          3 :         SvxCharHiddenItem aHidden(true, RES_CHRATR_HIDDEN);
     257         [ +  - ]:          3 :         m_pDoc->InsertPoolItem(aPaM, aHidden, 0 );
     258                 :            : 
     259                 :            :         //turn on red-lining and show changes
     260         [ +  - ]:          3 :         m_pDoc->SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT);
     261 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc->IsRedlineOn());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     262 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc->GetRedlineMode()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     263                 :            : 
     264                 :            :         //set start of selection to last A
     265 [ +  - ][ +  - ]:          3 :         aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 4);
     266         [ +  - ]:          3 :         aPaM.SetMark();
     267                 :            :         //set end of selection to second last B
     268 [ +  - ][ +  - ]:          3 :         aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 9);
     269         [ +  - ]:          3 :         m_pDoc->DeleteAndJoin(aPaM);    //redline-aware deletion api
     270                 :            : 
     271                 :            :         {
     272         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, PASSTHROUGH);
     273                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     274         [ +  - ]:          3 :             rtl::OUString sModelText = pTxtNode->GetTxt();
     275 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == sModelText);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     276                 :            :         }
     277                 :            : 
     278                 :            :         {
     279         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS);
     280                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     281 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == "AAAAA BBBBB foo CCCCC foo DDDDD");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     282                 :            :         }
     283                 :            : 
     284                 :            :         {
     285         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEINVISIBLE);
     286                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     287                 :          3 :             rtl::OUStringBuffer aBuffer;
     288         [ +  - ]:          3 :             aBuffer.append("AAAAA CCCCC ");
     289         [ +  - ]:          3 :             aBuffer.append(CH_TXTATR_BREAKWORD);
     290         [ +  - ]:          3 :             aBuffer.append(" DDDDD");
     291 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     292                 :            :         }
     293                 :            : 
     294                 :            :         {
     295         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEREDLINED);
     296                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     297                 :          3 :             rtl::OUStringBuffer aBuffer;
     298         [ +  - ]:          3 :             aBuffer.append("AAAABB ");
     299         [ +  - ]:          3 :             aBuffer.append(CH_TXTATR_BREAKWORD);
     300         [ +  - ]:          3 :             aBuffer.append(" CCCCC ");
     301         [ +  - ]:          3 :             aBuffer.append(CH_TXTATR_BREAKWORD);
     302         [ +  - ]:          3 :             aBuffer.append(" DDDDD");
     303 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     304                 :            :         }
     305                 :            : 
     306                 :            :         {
     307         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEINVISIBLE);
     308                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     309 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == "AAAAA CCCCC foo DDDDD");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     310                 :            :         }
     311                 :            : 
     312                 :            :         {
     313         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEREDLINED);
     314                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     315 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == "AAAABB foo CCCCC foo DDDDD");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     316                 :            :         }
     317                 :            : 
     318                 :            :         {
     319         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEINVISIBLE | HIDEREDLINED);
     320                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     321                 :          3 :             rtl::OUStringBuffer aBuffer;
     322         [ +  - ]:          3 :             aBuffer.append("AAAACCCCC ");
     323         [ +  - ]:          3 :             aBuffer.append(CH_TXTATR_BREAKWORD);
     324         [ +  - ]:          3 :             aBuffer.append(" DDDDD");
     325 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     326                 :            :         }
     327                 :            : 
     328                 :            :         {
     329         [ +  - ]:          3 :             ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEINVISIBLE | HIDEREDLINED);
     330                 :          3 :             rtl::OUString sViewText = aModelToViewHelper.getViewText();
     331 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT(sViewText == "AAAACCCCC foo DDDDD");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     332 [ +  - ][ +  - ]:          3 :         }
     333 [ +  - ][ +  - ]:          3 :     }
     334                 :          3 : }
     335                 :            : 
     336                 :          3 : void SwDocTest::testSwScanner()
     337                 :            : {
     338 [ +  - ][ +  - ]:          3 :     SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
     339         [ +  - ]:          3 :     SwPaM aPaM(aIdx);
     340                 :            : 
     341                 :          3 :     SwTxtNode* pTxtNode = aPaM.GetNode()->GetTxtNode();
     342                 :            : 
     343 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Has Text Node", pTxtNode);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     344                 :            : 
     345                 :            :     //See https://bugs.freedesktop.org/show_bug.cgi?id=40449
     346                 :            :     //See https://bugs.freedesktop.org/show_bug.cgi?id=39365
     347                 :            :     //Use a temporary rtl::OUString as the arg, as that's the trouble behind
     348                 :            :     //fdo#40449 and fdo#39365
     349                 :            :     {
     350                 :            :         SwScanner aScanner(*pTxtNode,
     351                 :            :             rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hello World")),
     352                 :            :             0, ModelToViewHelper(), i18n::WordType::DICTIONARY_WORD, 0,
     353 [ +  - ][ +  - ]:          3 :             RTL_CONSTASCII_LENGTH("Hello World"));
                 [ +  - ]
     354                 :            : 
     355         [ +  - ]:          3 :         bool bFirstOk = aScanner.NextWord();
     356 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("First Token", bFirstOk);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     357                 :          3 :         const rtl::OUString &rHello = aScanner.GetWord();
     358 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Should be Hello",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     359         [ +  - ]:          3 :             rHello.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Hello")));
     360                 :            : 
     361         [ +  - ]:          3 :         bool bSecondOk = aScanner.NextWord();
     362 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Second Token", bSecondOk);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     363                 :          3 :         const rtl::OUString &rWorld = aScanner.GetWord();
     364 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Should be World",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     365         [ +  - ]:          6 :             rWorld.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("World")));
     366                 :            :     }
     367                 :            : 
     368                 :            :     //See https://www.libreoffice.org/bugzilla/show_bug.cgi?id=45271
     369                 :            :     {
     370                 :          3 :         const sal_Unicode IDEOGRAPHICFULLSTOP_D[] = { 0x3002, 'D' };
     371                 :            : 
     372                 :            :         m_pDoc->InsertString(aPaM, rtl::OUString(IDEOGRAPHICFULLSTOP_D,
     373 [ +  - ][ +  - ]:          3 :             SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D)));
                 [ +  - ]
     374                 :            : 
     375         [ +  - ]:          3 :         SvxLanguageItem aCJKLangItem( LANGUAGE_CHINESE_SIMPLIFIED, RES_CHRATR_CJK_LANGUAGE );
     376         [ +  - ]:          3 :         SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
     377         [ +  - ]:          3 :         m_pDoc->InsertPoolItem(aPaM, aCJKLangItem, 0 );
     378         [ +  - ]:          3 :         m_pDoc->InsertPoolItem(aPaM, aWestLangItem, 0 );
     379                 :            : 
     380         [ +  - ]:          3 :         SwDocStat aDocStat;
     381                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     382         [ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(IDEOGRAPHICFULLSTOP_D));
     383                 :            : 
     384 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should be 2", aDocStat.nChar == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     385 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should be 2", aDocStat.nCharExcludingSpaces == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     386                 :            :     }
     387                 :            :     {
     388                 :            :         const sal_Unicode test[] =
     389                 :            :         {
     390                 :            :             0x3053, 0x306E, 0x65E5, 0x672C, 0x8A9E, 0x306F, 0x6B63, 0x3057,
     391                 :            :             0x304F, 0x6570, 0x3048, 0x3089, 0x308C, 0x308B, 0x3067, 0x3057,
     392                 :            :             0x3087, 0x3046, 0x304B, 0x3002, 0x0041, 0x006E, 0x0064, 0x0020,
     393                 :            :             0x006C, 0x0065, 0x0074, 0x0027, 0x0073, 0x0020, 0x0074, 0x0068,
     394                 :            :             0x0072, 0x006F, 0x0077, 0x0020, 0x0073, 0x006F, 0x006D, 0x0065,
     395                 :            :             0x0020, 0x0045, 0x006E, 0x0067, 0x006C, 0x0069, 0x0073, 0x0068,
     396                 :            :             0x0020, 0x0069, 0x006E, 0x0020, 0x0074, 0x006F, 0x0020, 0x006D,
     397                 :            :             0x0061, 0x006B, 0x0065, 0x0020, 0x0069, 0x0074, 0x0020, 0x0069,
     398                 :            :             0x006E, 0x0074, 0x0065, 0x0072, 0x0065, 0x0073, 0x0074, 0x0069,
     399                 :            :             0x006E, 0x0067, 0x002E, 0x0020, 0x0020, 0x305D, 0x3057, 0x3066,
     400                 :            :             0x3001, 0x307E, 0x305F, 0x65E5, 0x672C, 0x8A9E, 0x3000, 0x3000,
     401                 :            :             0x3067, 0x3082, 0x4ECA, 0x56DE, 0x306F, 0x7A7A, 0x767D, 0x3092,
     402                 :            :             0x3000, 0x3000, 0x5165, 0x308C, 0x307E, 0x3057, 0x305F, 0x3002,
     403                 :            :             0x0020, 0x0020, 0x0053, 0x006F, 0x0020, 0x0068, 0x006F, 0x0077,
     404                 :            :             0x0020, 0x0064, 0x006F, 0x0065, 0x0073, 0x0020, 0x0074, 0x0068,
     405                 :            :             0x0069, 0x0073, 0x0020, 0x0064, 0x006F, 0x003F, 0x0020, 0x0020
     406                 :          3 :         };
     407         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     408                 :            :         m_pDoc->InsertString(aPaM, rtl::OUString(test,
     409 [ +  - ][ +  - ]:          3 :             SAL_N_ELEMENTS(test)));
                 [ +  - ]
     410                 :            : 
     411         [ +  - ]:          3 :         SvxLanguageItem aCJKLangItem( LANGUAGE_JAPANESE, RES_CHRATR_CJK_LANGUAGE );
     412         [ +  - ]:          3 :         SvxLanguageItem aWestLangItem( LANGUAGE_ENGLISH_US, RES_CHRATR_LANGUAGE );
     413         [ +  - ]:          3 :         m_pDoc->InsertPoolItem(aPaM, aCJKLangItem, 0 );
     414         [ +  - ]:          3 :         m_pDoc->InsertPoolItem(aPaM, aWestLangItem, 0 );
     415                 :            : 
     416         [ +  - ]:          3 :         SwDocStat aDocStat;
     417                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     418         [ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(test));
     419 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("58 words", aDocStat.nWord == 58);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     420 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("43 Asian characters and Korean syllables", aDocStat.nAsianWord == 43);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     421 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("105 non-whitespace chars", aDocStat.nCharExcludingSpaces == 105);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     422 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("128 characters", aDocStat.nChar == 128);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     423                 :            :     }
     424                 :            : 
     425                 :            :     //See https://issues.apache.org/ooo/show_bug.cgi?id=89042
     426                 :            :     //See https://bugs.freedesktop.org/show_bug.cgi?id=53399
     427                 :            :     {
     428         [ +  - ]:          3 :         SwDocStat aDocStat;
     429                 :            : 
     430                 :            :         const sal_Unicode aShouldBeThree[] = {
     431                 :            :             0x0053, 0x0068, 0x006F, 0x0075, 0x006C, 0x0064, 0x0020,
     432                 :            :             0x2018, 0x0062, 0x0065, 0x0020, 0x0074, 0x0068, 0x0072,
     433                 :            :             0x0065, 0x0065, 0x2019
     434                 :          3 :         };
     435                 :            : 
     436         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     437 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString(aShouldBeThree, SAL_N_ELEMENTS(aShouldBeThree)));
                 [ +  - ]
     438                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     439         [ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(aShouldBeThree));
     440 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should be 3", aDocStat.nWord == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     441                 :            : 
     442                 :            :         const sal_Unicode aShouldBeFive[] = {
     443                 :            :             // f    r       e       n       c       h       space
     444                 :            :             0x0046, 0x0072, 0x0065, 0x006E, 0x0063, 0x0068, 0x0020,
     445                 :            :             // <<   nbsp    s       a       v       o       i
     446                 :            :             0x00AB, 0x00A0, 0x0073, 0x0061, 0x0076, 0x006F, 0x0069,
     447                 :            :             // r    nnbsp   c       a       l       c       u
     448                 :            :             0x0072, 0x202f, 0x0063, 0x0061, 0x006C, 0x0063, 0x0075,
     449                 :            :             // l    e       r       idspace >>
     450                 :            :             0x006C, 0x0065, 0x0072, 0x3000, 0x00BB
     451                 :          3 :         };
     452                 :            : 
     453         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     454 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString(aShouldBeFive, SAL_N_ELEMENTS(aShouldBeFive)));
                 [ +  - ]
     455                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     456         [ +  - ]:          3 :         aDocStat.Reset();
     457         [ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, SAL_N_ELEMENTS(aShouldBeFive));
     458 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should be 5", aDocStat.nWord == 5);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     459                 :            :     }
     460                 :            : 
     461                 :            :     //See https://bugs.freedesktop.org/show_bug.cgi?id=49629
     462                 :            :     {
     463         [ +  - ]:          3 :         SwDocStat aDocStat;
     464                 :            : 
     465         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     466 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString("Apple"));
                 [ +  - ]
     467                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     468                 :          3 :         xub_StrLen nPos = aPaM.GetPoint()->nContent.GetIndex();
     469         [ +  - ]:          3 :         SwFmtFtn aFtn;
     470 [ +  - ][ +  - ]:          3 :         aFtn.SetNumStr(rtl::OUString("banana"));
                 [ +  - ]
     471         [ +  - ]:          3 :         SwTxtAttr* pTA = pTxtNode->InsertItem(aFtn, nPos, nPos);
     472 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pTA);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     473 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pTxtNode->Len() == 6); //Apple + 0x02
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     474 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len());
     475 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(aDocStat.nWord == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     476 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("footnote should be expanded", aDocStat.nChar == 11);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     477                 :            : 
     478                 :          3 :         xub_StrLen nNextPos = aPaM.GetPoint()->nContent.GetIndex();
     479 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(nNextPos == nPos+1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     480 [ +  - ][ +  - ]:          3 :         SwFmtRefMark aRef(rtl::OUString("refmark"));
                 [ +  - ]
     481         [ +  - ]:          3 :         pTA = pTxtNode->InsertItem(aRef, nNextPos, nNextPos);
     482 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pTA);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     483                 :            : 
     484         [ +  - ]:          3 :         aDocStat.Reset();
     485         [ +  - ]:          3 :         pTxtNode->SetWordCountDirty(true);
     486 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len());
     487 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(aDocStat.nWord == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     488 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("refmark anchor should not be counted", aDocStat.nChar == 11);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     489                 :            : 
     490         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     491 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString("Apple"));
                 [ +  - ]
     492                 :            : 
     493         [ +  - ]:          3 :         DateTime aDate(DateTime::SYSTEM);
     494                 :            :         SwPostItField aPostIt(
     495         [ +  - ]:          3 :             (SwPostItFieldType*)m_pDoc->GetSysFldType(RES_POSTITFLD), rtl::OUString("An Author"),
     496 [ +  - ][ +  - ]:          6 :             rtl::OUString("Some Text"), rtl::OUString("Initials"), OUString("Name"), aDate );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     497 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertPoolItem(aPaM, SwFmtFld(aPostIt), 0);
                 [ +  - ]
     498                 :            : 
     499 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString("Apple"));
                 [ +  - ]
     500                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     501         [ +  - ]:          3 :         aDocStat.Reset();
     502 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len());
     503 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(aDocStat.nWord == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     504 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("postit anchor should effectively not exist", aDocStat.nChar == 10);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     505 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pTxtNode->Len() == 11);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     506                 :            : 
     507 [ +  - ][ +  - ]:          3 :         aDocStat.Reset();
         [ +  - ][ +  - ]
     508                 :            :     }
     509                 :            : 
     510                 :            :     //See https://bugs.freedesktop.org/show_bug.cgi?id=46757
     511                 :            :     {
     512         [ +  - ]:          3 :         SwDocStat aDocStat;
     513                 :            : 
     514                 :          3 :         const char aString[] = "Lorem ipsum";
     515         [ +  - ]:          3 :         m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     516 [ +  - ][ +  - ]:          3 :         m_pDoc->InsertString(aPaM, rtl::OUString(aString));
                 [ +  - ]
     517                 :          3 :         pTxtNode = aPaM.GetNode()->GetTxtNode();
     518 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len());
     519 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(2));
         [ +  - ][ +  - ]
                 [ +  - ]
     520                 :            : 
     521                 :            :         //turn on red-lining and show changes
     522         [ +  - ]:          3 :         m_pDoc->SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT);
     523 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc->IsRedlineOn());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     524 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc->GetRedlineMode()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     525                 :            : 
     526                 :            :         //delete everything except the first word
     527         [ +  - ]:          3 :         aPaM.SetMark(); //set start of selection to current pos
     528 [ +  - ][ +  - ]:          3 :         aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 5);   //set end of selection to fifth char of current node
     529         [ +  - ]:          3 :         m_pDoc->DeleteAndJoin(aPaM);    //redline-aware deletion api
     530 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("real underlying text should be the same", pTxtNode->GetTxt().EqualsAscii(aString));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     531                 :            : 
     532         [ +  - ]:          3 :         aDocStat.Reset();
     533         [ +  - ]:          3 :         pTxtNode->SetWordCountDirty(true);
     534 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len()); //but word-counting the text should only count the non-deleted text
     535 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(1));
         [ +  - ][ +  - ]
                 [ +  - ]
     536                 :            : 
     537         [ +  - ]:          3 :         pTxtNode->SetWordCountDirty(true);
     538                 :            : 
     539                 :            :         //keep red-lining on but hide changes
     540         [ +  - ]:          3 :         m_pDoc->SetRedlineMode(nsRedlineMode_t::REDLINE_ON);
     541 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("redlining should be still on", m_pDoc->IsRedlineOn());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     542 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("redlines should be invisible", !IDocumentRedlineAccess::IsShowChanges(m_pDoc->GetRedlineMode()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     543                 :            : 
     544         [ +  - ]:          3 :         aDocStat.Reset();
     545 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len()); //but word-counting the text should only count the non-deleted text
     546 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(1));
         [ +  - ][ +  - ]
                 [ +  - ]
     547                 :            : 
     548         [ +  - ]:          3 :         rtl::OUString sLorem = pTxtNode->GetTxt();
     549 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(sLorem == "Lorem");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     550                 :            : 
     551         [ +  - ]:          3 :         const SwRedlineTbl& rTbl = m_pDoc->GetRedlineTbl();
     552                 :            : 
     553         [ +  - ]:          3 :         SwNodes& rNds = m_pDoc->GetNodes();
     554 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(rTbl.size() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     555                 :            : 
     556         [ +  - ]:          3 :         SwNodeIndex* pNodeIdx = rTbl[0]->GetContentIdx();
     557 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pNodeIdx);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     558                 :            : 
     559         [ +  - ]:          3 :         pTxtNode = rNds[ pNodeIdx->GetIndex() + 1 ]->GetTxtNode();        //first deleted txtnode
     560 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(pTxtNode);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     561                 :            : 
     562         [ +  - ]:          3 :         rtl::OUString sIpsum = pTxtNode->GetTxt();
     563 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT(sIpsum == " ipsum");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     564                 :            : 
     565         [ +  - ]:          3 :         aDocStat.Reset();
     566 [ +  - ][ +  - ]:          3 :         pTxtNode->CountWords(aDocStat, 0, pTxtNode->Len()); //word-counting the text should only count the non-deleted text, and this whole chunk should be ignored
     567 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_EQUAL(aDocStat.nWord, static_cast<sal_uLong>(0));
         [ +  - ][ +  - ]
                 [ +  - ]
     568 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_EQUAL(aDocStat.nChar, static_cast<sal_uLong>(0));
         [ +  - ][ +  - ]
                 [ +  - ]
     569 [ +  - ][ +  - ]:          3 :     }
     570                 :          3 : }
     571                 :            : 
     572                 :            : //See https://bugs.freedesktop.org/show_bug.cgi?id=40599
     573                 :          3 : void SwDocTest::testGraphicAnchorDeletion()
     574                 :            : {
     575 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Expected initial 0 count", m_pDoc->GetDocStat().nChar == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     576                 :            : 
     577 [ +  - ][ +  - ]:          3 :     SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
     578         [ +  - ]:          3 :     SwPaM aPaM(aIdx);
     579                 :            : 
     580 [ +  - ][ +  - ]:          3 :     m_pDoc->InsertString(aPaM, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Paragraph 1")));
         [ +  - ][ +  - ]
     581         [ +  - ]:          3 :     m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     582                 :            : 
     583 [ +  - ][ +  - ]:          3 :     m_pDoc->InsertString(aPaM, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("graphic anchor>><<graphic anchor")));
         [ +  - ][ +  - ]
     584         [ +  - ]:          3 :     SwNodeIndex nPara2 = aPaM.GetPoint()->nNode;
     585         [ +  - ]:          3 :     m_pDoc->AppendTxtNode(*aPaM.GetPoint());
     586                 :            : 
     587 [ +  - ][ +  - ]:          3 :     m_pDoc->InsertString(aPaM, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Paragraph 3")));
         [ +  - ][ +  - ]
     588                 :            : 
     589         [ +  - ]:          3 :     aPaM.GetPoint()->nNode = nPara2;
     590 [ +  - ][ +  - ]:          3 :     aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), RTL_CONSTASCII_LENGTH("graphic anchor>>"));
     591                 :            : 
     592                 :            :     //Insert a graphic at X of >>X<< in paragraph 2
     593         [ +  - ]:          3 :     SfxItemSet aFlySet(m_pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
     594         [ +  - ]:          3 :     SwFmtAnchor aAnchor(FLY_AS_CHAR);
     595         [ +  - ]:          3 :     aAnchor.SetAnchor(aPaM.GetPoint());
     596         [ +  - ]:          3 :     aFlySet.Put(aAnchor);
     597 [ +  - ][ +  - ]:          3 :     SwFlyFrmFmt *pFrame = m_pDoc->Insert(aPaM, rtl::OUString(), rtl::OUString(), NULL, &aFlySet, NULL, NULL);
         [ +  - ][ +  - ]
                 [ +  - ]
     598 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Expected frame", pFrame != NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     599                 :            : 
     600 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Should be 1 graphic", m_pDoc->GetFlyCount(FLYCNTTYPE_GRF) == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     601                 :            : 
     602                 :            :     //Delete >X<
     603         [ +  - ]:          3 :     aPaM.GetPoint()->nNode = nPara2;
     604                 :          6 :     aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(),
     605 [ +  - ][ +  - ]:          6 :         RTL_CONSTASCII_LENGTH("graphic anchor>><")+1);
     606         [ +  - ]:          3 :     aPaM.SetMark();
     607         [ +  - ]:          3 :     aPaM.GetPoint()->nNode = nPara2;
     608 [ +  - ][ +  - ]:          3 :     aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), RTL_CONSTASCII_LENGTH("graphic anchor>"));
     609         [ +  - ]:          3 :     m_pDoc->DeleteRange(aPaM);
     610                 :            : 
     611                 :            : #ifdef DEBUG_AS_HTML
     612                 :            :     {
     613                 :            :         SvFileStream aPasteDebug(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
     614                 :            :             "cppunitDEBUG.html")), STREAM_WRITE|STREAM_TRUNC);
     615                 :            :         WriterRef xWrt;
     616                 :            :         GetHTMLWriter( String(), String(), xWrt );
     617                 :            :         SwWriter aDbgWrt( aPasteDebug, *m_pDoc );
     618                 :            :         aDbgWrt.Write( xWrt );
     619                 :            :     }
     620                 :            : #endif
     621                 :            : 
     622 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Should be 0 graphics", m_pDoc->GetFlyCount(FLYCNTTYPE_GRF) == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     623                 :            : 
     624                 :            :     //Now, if instead we swap FLY_AS_CHAR (inline graphic) to FLY_AT_CHAR (anchored to character)
     625                 :            :     //and repeat the above, graphic is *not* deleted, i.e. it belongs to the paragraph, not the
     626                 :            :     //range to which its anchored, which is annoying.
     627                 :          3 : }
     628                 :            : 
     629                 :            : static int
     630                 :     109532 : getRand(int modulus)
     631                 :            : {
     632         [ -  + ]:     109532 :     if (modulus <= 0)
     633                 :          0 :         return 0;
     634                 :     109532 :     return rand() % modulus;
     635                 :            : }
     636                 :            : 
     637                 :            : static rtl::OUString
     638                 :      12103 : getRandString()
     639                 :            : {
     640                 :      12103 :     rtl::OUString aText("AAAAA BBBB CCC DD E \n");
     641                 :      12103 :     int s = getRand(aText.getLength());
     642                 :      12103 :     int j = getRand(aText.getLength() - s);
     643                 :      12103 :     rtl::OUString aRet(aText.copy(s, j));
     644         [ +  + ]:      12103 :     if (!getRand(5))
     645                 :       2468 :         aRet += rtl::OUString(sal_Unicode('\n'));
     646                 :            : //    fprintf (stderr, "rand string '%s'\n", OUStringToOString(aRet, RTL_TEXTENCODING_UTF8).getStr());
     647                 :      12103 :     return aRet;
     648                 :            : }
     649                 :            : 
     650                 :            : static SwPosition
     651                 :      55730 : getRandomPosition(SwDoc *pDoc, int /* nOffset */)
     652                 :            : {
     653 [ +  - ][ +  - ]:      55730 :     const SwPosition aPos(pDoc->GetNodes().GetEndOfContent());
     654                 :      55730 :         sal_uLong nNodes = aPos.nNode.GetNode().GetIndex() - aPos.nNode.GetNode().StartOfSectionIndex();
     655                 :      55730 :         sal_uLong n = (rand() * nNodes) / RAND_MAX;
     656         [ +  - ]:      55730 :         SwPaM pam(aPos);
     657         [ +  + ]:      83542 :         for (sal_uLong i = 0; i < n; ++i) {
     658         [ +  - ]:      27812 :                 pam.Move(fnMoveBackward, fnGoNode);
     659                 :            :         }
     660 [ +  - ][ +  - ]:      55730 :     return *pam.GetPoint();
                 [ +  - ]
     661                 :            : }
     662                 :            : 
     663                 :          3 : void SwDocTest::randomTest()
     664                 :            : {
     665 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("SwDoc::IsRedlineOn()", !m_pDoc->IsRedlineOn());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     666                 :            :     RedlineMode_t modes[] = {
     667                 :            :         nsRedlineMode_t::REDLINE_ON,
     668                 :            :         nsRedlineMode_t::REDLINE_SHOW_MASK,
     669                 :            :         nsRedlineMode_t::REDLINE_NONE,
     670                 :            :         nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_MASK,
     671                 :            :         nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE,
     672                 :            :         nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE | nsRedlineMode_t::REDLINE_SHOW_MASK,
     673                 :            :         nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT,
     674                 :            :         nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE
     675                 :          3 :     };
     676                 :            :     static const char *authors[] = {
     677                 :            :         "Jim", "Bob", "JimBobina", "Helga", "Gertrude", "Spagna", "Hurtleweed"
     678                 :            :     };
     679                 :            : 
     680         [ +  + ]:         27 :     for( sal_uInt16 rlm = 0; rlm < SAL_N_ELEMENTS(modes); rlm++ )
     681                 :            :     {
     682         [ +  - ]:         24 :         m_pDoc->ClearDoc();
     683                 :            : 
     684                 :            :         // setup redlining
     685         [ +  - ]:         24 :         m_pDoc->SetRedlineMode(modes[rlm]);
     686 [ +  - ][ +  - ]:         24 :         SW_MOD()->SetRedlineAuthor(rtl::OUString::createFromAscii(authors[0]));
         [ +  - ][ +  - ]
     687                 :            : 
     688         [ +  + ]:      48024 :         for( int i = 0; i < 2000; i++ )
     689                 :            :         {
     690 [ +  - ][ +  - ]:      48000 :             SwPaM aPam(m_pDoc->GetNodes());
         [ +  - ][ +  - ]
     691 [ +  - ][ +  - ]:      48000 :             SwCursor aCrs(getRandomPosition(m_pDoc, i/20), 0, false);
                 [ +  - ]
     692         [ +  - ]:      48000 :             aCrs.SetMark();
     693                 :            : 
     694 [ +  + ][ +  +  :      48000 :             switch (getRand (i < 50 ? 3 : 6)) {
             +  +  +  +  
                      - ]
     695                 :            :             // insert ops first
     696                 :            :             case 0: {
     697 [ +  - ][ +  - ]:       8183 :                 if (!m_pDoc->InsertString(aCrs, getRandString())) {
         [ +  - ][ +  - ]
     698                 :            : //                    fprintf (stderr, "failed to insert string !\n");
     699                 :            :                 }
     700                 :       8183 :                 break;
     701                 :            :             }
     702                 :            :             case 1:
     703                 :       8193 :                 break;
     704                 :            :             case 2: { // switch author
     705                 :       8338 :                 int a = getRand(SAL_N_ELEMENTS(authors));
     706 [ +  - ][ +  - ]:       8338 :                 SW_MOD()->SetRedlineAuthor(rtl::OUString::createFromAscii(authors[a]));
         [ +  - ][ +  - ]
     707                 :       8338 :                 break;
     708                 :            :             }
     709                 :            : 
     710                 :            :             // movement / deletion ops later
     711                 :            :             case 3: // deletion
     712   [ +  +  +  + ]:       7821 :                 switch (getRand(6)) {
     713                 :            :                 case 0:
     714         [ +  - ]:       1246 :                     m_pDoc->DelFullPara(aCrs);
     715                 :       1246 :                     break;
     716                 :            :                 case 1:
     717         [ +  - ]:       1321 :                     m_pDoc->DeleteRange(aCrs);
     718                 :       1321 :                     break;
     719                 :            :                 case 2:
     720         [ +  - ]:       1334 :                     m_pDoc->DeleteAndJoin(aCrs, !!getRand(1));
     721                 :       1334 :                     break;
     722                 :            :                 case 3:
     723                 :            :                 default:
     724 [ +  - ][ +  - ]:       3920 :                     m_pDoc->Overwrite(aCrs, getRandString());
         [ +  - ][ +  - ]
     725                 :       3920 :                     break;
     726                 :            :                 }
     727                 :       7821 :                 break;
     728                 :            :             case 4: { // movement
     729                 :            :                 IDocumentContentOperations::SwMoveFlags nFlags =
     730                 :            :                     (IDocumentContentOperations::SwMoveFlags)
     731                 :       7730 :                         (getRand(1) ? // FIXME: puterb this more ?
     732                 :            :                          IDocumentContentOperations::DOC_MOVEDEFAULT :
     733                 :            :                          IDocumentContentOperations::DOC_MOVEALLFLYS |
     734                 :            :                          IDocumentContentOperations::DOC_CREATEUNDOOBJ |
     735                 :            :                          IDocumentContentOperations::DOC_MOVEREDLINES |
     736         [ -  + ]:       7730 :                          IDocumentContentOperations::DOC_NO_DELFRMS);
     737         [ +  - ]:       7730 :                 SwPosition aTo(getRandomPosition(m_pDoc, i/10));
     738         [ +  - ]:       7730 :                 m_pDoc->MoveRange(aCrs, aTo, nFlags);
     739         [ +  - ]:       7730 :                 break;
     740                 :            :             }
     741                 :            : 
     742                 :            :             case 5:
     743                 :       7735 :                 break;
     744                 :            : 
     745                 :            :             // undo / redo ?
     746                 :            :             default:
     747                 :          0 :                 break;
     748                 :            :             }
     749 [ +  - ][ +  - ]:      48000 :         }
     750                 :            : 
     751                 :            : // Debug / verify the produced document has real content
     752                 :            : #if 0
     753                 :            :         rtl::OStringBuffer aBuffer("nodes-");
     754                 :            :         aBuffer.append(sal_Int32(rlm));
     755                 :            :         aBuffer.append(".xml");
     756                 :            : 
     757                 :            :         xmlTextWriterPtr writer;
     758                 :            :         writer = xmlNewTextWriterFilename( aBuffer.makeStringAndClear().getStr(), 0 );
     759                 :            :         xmlTextWriterStartDocument( writer, NULL, NULL, NULL );
     760                 :            :         m_pDoc->dumpAsXml(writer);
     761                 :            :         xmlTextWriterEndDocument( writer );
     762                 :            :         xmlFreeTextWriter( writer );
     763                 :            : #endif
     764                 :            :     }
     765                 :          3 : }
     766                 :            : 
     767                 :         24 : void SwDocTest::setUp()
     768                 :            : {
     769                 :         24 :     BootstrapFixture::setUp();
     770                 :            : 
     771                 :         24 :     SwGlobals::ensure();
     772         [ +  - ]:         24 :     m_pDoc = new SwDoc;
     773         [ +  - ]:         24 :     m_xDocShRef = new SwDocShell(m_pDoc, SFX_CREATE_MODE_EMBEDDED);
     774                 :         24 :     m_xDocShRef->DoInitNew(0);
     775                 :         24 : }
     776                 :            : 
     777                 :         24 : void SwDocTest::tearDown()
     778                 :            : {
     779                 :         24 :     m_xDocShRef.Clear();
     780         [ +  - ]:         24 :     delete m_pDoc;
     781                 :            : 
     782                 :         24 :     BootstrapFixture::tearDown();
     783                 :         24 : }
     784                 :            : 
     785                 :          3 : CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);
     786                 :            : 
     787 [ +  - ][ +  - ]:         12 : CPPUNIT_PLUGIN_IMPLEMENT();
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
     788                 :            : 
     789                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10