LCOV - code coverage report
Current view: top level - sw/source/core/doc - docruby.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1 147 0.7 %
Date: 2015-06-13 12:38:46 Functions: 2 6 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <string.h>
      21             : 
      22             : #include <com/sun/star/i18n/UnicodeType.hpp>
      23             : #include <com/sun/star/i18n/WordType.hpp>
      24             : 
      25             : #include <unotools/charclass.hxx>
      26             : 
      27             : #include <hintids.hxx>
      28             : #include <doc.hxx>
      29             : #include <IDocumentUndoRedo.hxx>
      30             : #include <IDocumentContentOperations.hxx>
      31             : #include <docary.hxx>
      32             : #include <mvsave.hxx>
      33             : #include <ndtxt.hxx>
      34             : #include <txatbase.hxx>
      35             : #include <rubylist.hxx>
      36             : #include <pam.hxx>
      37             : #include <swundo.hxx>
      38             : #include <breakit.hxx>
      39             : #include <crsskip.hxx>
      40             : 
      41             : using namespace ::com::sun::star::i18n;
      42             : 
      43             : /*
      44             :  * Members in the list:
      45             :  *   - String - the orig text
      46             :  *   - SwFormatRuby - the ruby attribute
      47             :  */
      48           0 : sal_uInt16 SwDoc::FillRubyList( const SwPaM& rPam, SwRubyList& rList,
      49             :                             sal_uInt16 nMode )
      50             : {
      51           0 :     const SwPaM *_pStartCrsr = rPam.GetNext(),
      52           0 :                 *__pStartCrsr = _pStartCrsr;
      53           0 :     bool bCheckEmpty = &rPam != _pStartCrsr;
      54           0 :     do {
      55           0 :         const SwPosition* pStt = _pStartCrsr->Start(),
      56           0 :                         * pEnd = pStt == _pStartCrsr->GetPoint()
      57             :                                                 ? _pStartCrsr->GetMark()
      58           0 :                                                 : _pStartCrsr->GetPoint();
      59           0 :         if( !bCheckEmpty || ( pStt != pEnd && *pStt != *pEnd ))
      60             :         {
      61           0 :             SwPaM aPam( *pStt );
      62           0 :             do {
      63           0 :                 SwRubyListEntry* pNew = new SwRubyListEntry;
      64           0 :                 if( pEnd != pStt )
      65             :                 {
      66           0 :                     aPam.SetMark();
      67           0 :                     *aPam.GetMark() = *pEnd;
      68             :                 }
      69           0 :                 if( _SelectNextRubyChars( aPam, *pNew, nMode ))
      70             :                 {
      71           0 :                     rList.push_back( pNew );
      72           0 :                     aPam.DeleteMark();
      73             :                 }
      74             :                 else
      75             :                 {
      76           0 :                     delete pNew;
      77           0 :                      if( *aPam.GetPoint() < *pEnd )
      78             :                      {
      79             :                         // goto next paragraph
      80           0 :                         aPam.DeleteMark();
      81           0 :                         aPam.Move( fnMoveForward, fnGoNode );
      82             :                      }
      83             :                      else
      84           0 :                         break;
      85             :                 }
      86           0 :             } while( 30 > rList.size() && *aPam.GetPoint() < *pEnd );
      87             :         }
      88           0 :     } while( 30 > rList.size() &&
      89             :         (_pStartCrsr = _pStartCrsr->GetNext()) != __pStartCrsr );
      90             : 
      91           0 :     return rList.size();
      92             : }
      93             : 
      94           0 : sal_uInt16 SwDoc::SetRubyList( const SwPaM& rPam, const SwRubyList& rList,
      95             :                             sal_uInt16 nMode )
      96             : {
      97           0 :     GetIDocumentUndoRedo().StartUndo( UNDO_SETRUBYATTR, NULL );
      98           0 :     std::set<sal_uInt16> aDelArr;
      99           0 :     aDelArr.insert( RES_TXTATR_CJK_RUBY );
     100             : 
     101           0 :     sal_uInt16 nListEntry = 0;
     102             : 
     103           0 :     const SwPaM *_pStartCrsr = rPam.GetNext(),
     104           0 :                 *__pStartCrsr = _pStartCrsr;
     105           0 :     bool bCheckEmpty = &rPam != _pStartCrsr;
     106           0 :     do {
     107           0 :         const SwPosition* pStt = _pStartCrsr->Start(),
     108           0 :                         * pEnd = pStt == _pStartCrsr->GetPoint()
     109             :                                                 ? _pStartCrsr->GetMark()
     110           0 :                                                 : _pStartCrsr->GetPoint();
     111           0 :         if( !bCheckEmpty || ( pStt != pEnd && *pStt != *pEnd ))
     112             :         {
     113             : 
     114           0 :             SwPaM aPam( *pStt );
     115           0 :             do {
     116           0 :                 SwRubyListEntry aCheckEntry;
     117           0 :                 if( pEnd != pStt )
     118             :                 {
     119           0 :                     aPam.SetMark();
     120           0 :                     *aPam.GetMark() = *pEnd;
     121             :                 }
     122           0 :                 if( _SelectNextRubyChars( aPam, aCheckEntry, nMode ))
     123             :                 {
     124           0 :                     const SwRubyListEntry* pEntry = &rList[ nListEntry++ ];
     125           0 :                     if( aCheckEntry.GetRubyAttr() != pEntry->GetRubyAttr() )
     126             :                     {
     127             :                         // set/reset the attribute
     128           0 :                         if( !pEntry->GetRubyAttr().GetText().isEmpty() )
     129             :                         {
     130           0 :                             getIDocumentContentOperations().InsertPoolItem( aPam, pEntry->GetRubyAttr() );
     131             :                         }
     132             :                         else
     133             :                         {
     134           0 :                             ResetAttrs( aPam, true, aDelArr );
     135             :                         }
     136             :                     }
     137             : 
     138           0 :                     if( !pEntry->GetText().isEmpty() &&
     139           0 :                         aCheckEntry.GetText() != pEntry->GetText() )
     140             :                     {
     141             :                         // text is changed, so replace the original
     142           0 :                         getIDocumentContentOperations().ReplaceRange( aPam, pEntry->GetText(), false );
     143             :                     }
     144           0 :                     aPam.DeleteMark();
     145             :                 }
     146             :                 else
     147             :                 {
     148           0 :                      if( *aPam.GetPoint() < *pEnd )
     149             :                      {
     150             :                         // goto next paragraph
     151           0 :                         aPam.DeleteMark();
     152           0 :                         aPam.Move( fnMoveForward, fnGoNode );
     153             :                      }
     154             :                      else
     155             :                     {
     156           0 :                         const SwRubyListEntry* pEntry = &rList[ nListEntry++ ];
     157             : 
     158             :                         // set/reset the attribute
     159           0 :                         if( !pEntry->GetRubyAttr().GetText().isEmpty() &&
     160           0 :                             !pEntry->GetText().isEmpty() )
     161             :                         {
     162           0 :                             getIDocumentContentOperations().InsertString( aPam, pEntry->GetText() );
     163           0 :                             aPam.SetMark();
     164           0 :                             aPam.GetMark()->nContent -= pEntry->GetText().getLength();
     165           0 :                             getIDocumentContentOperations().InsertPoolItem(
     166           0 :                                 aPam, pEntry->GetRubyAttr(), SetAttrMode::DONTEXPAND );
     167             :                         }
     168             :                         else
     169           0 :                             break;
     170           0 :                         aPam.DeleteMark();
     171             :                     }
     172           0 :                 }
     173           0 :             } while( nListEntry < rList.size() && *aPam.GetPoint() < *pEnd );
     174             :         }
     175           0 :     } while( 30 > rList.size() &&
     176             :         (_pStartCrsr = _pStartCrsr->GetNext()) != __pStartCrsr );
     177             : 
     178           0 :     GetIDocumentUndoRedo().EndUndo( UNDO_SETRUBYATTR, NULL );
     179             : 
     180           0 :     return nListEntry;
     181             : }
     182             : 
     183           0 : bool SwDoc::_SelectNextRubyChars( SwPaM& rPam, SwRubyListEntry& rEntry, sal_uInt16 )
     184             : {
     185             :     // Point must be the startposition, Mark is optional the end position
     186           0 :     SwPosition* pPos = rPam.GetPoint();
     187           0 :        const SwTextNode* pTNd = pPos->nNode.GetNode().GetTextNode();
     188           0 :     OUString const& rText = pTNd->GetText();
     189           0 :     sal_Int32 nStart = pPos->nContent.GetIndex();
     190           0 :     sal_Int32 nEnd = rText.getLength();
     191             : 
     192           0 :     bool bHasMark = rPam.HasMark();
     193           0 :     if( bHasMark )
     194             :     {
     195             :         // in the same node?
     196           0 :         if( rPam.GetMark()->nNode == pPos->nNode )
     197             :         {
     198             :             // then use that end
     199           0 :             const sal_Int32 nTEnd = rPam.GetMark()->nContent.GetIndex();
     200           0 :             if( nTEnd < nEnd )
     201           0 :                 nEnd = nTEnd;
     202             :         }
     203           0 :         rPam.DeleteMark();
     204             :     }
     205             : 
     206             :     // search the start
     207             :     // look where a ruby attribute starts
     208           0 :     const SwpHints* pHts = pTNd->GetpSwpHints();
     209           0 :     const SwTextAttr* pAttr = 0;
     210           0 :     if( pHts )
     211             :     {
     212           0 :         for( size_t nHtIdx = 0; nHtIdx < pHts->Count(); ++nHtIdx )
     213             :         {
     214           0 :             const SwTextAttr* pHt = (*pHts)[ nHtIdx ];
     215           0 :             if( RES_TXTATR_CJK_RUBY == pHt->Which() &&
     216           0 :                 *pHt->GetAnyEnd() > nStart )
     217             :             {
     218           0 :                 if( pHt->GetStart() < nEnd )
     219             :                 {
     220           0 :                     pAttr = pHt;
     221           0 :                     if( !bHasMark && nStart > pAttr->GetStart() )
     222             :                     {
     223           0 :                         nStart = pAttr->GetStart();
     224           0 :                         pPos->nContent = nStart;
     225             :                     }
     226             :                 }
     227           0 :                 break;
     228             :             }
     229             :         }
     230             :     }
     231             : 
     232           0 :     if( !bHasMark && nStart && ( !pAttr || nStart != pAttr->GetStart()) )
     233             :     {
     234             :         // skip to the word begin!
     235           0 :         const sal_Int32 nWordStt = g_pBreakIt->GetBreakIter()->getWordBoundary(
     236             :                             rText, nStart,
     237           0 :                             g_pBreakIt->GetLocale( pTNd->GetLang( nStart )),
     238             :                             WordType::ANYWORD_IGNOREWHITESPACES,
     239           0 :                             true ).startPos;
     240           0 :         if (nWordStt < nStart && nWordStt >= 0)
     241             :         {
     242           0 :             nStart = nWordStt;
     243           0 :             pPos->nContent = nStart;
     244             :         }
     245             :     }
     246             : 
     247           0 :     bool bAlphaNum = false;
     248           0 :     sal_Int32 nWordEnd = nEnd;
     249           0 :     CharClass& rCC = GetAppCharClass();
     250           0 :     while(  nStart < nEnd )
     251             :     {
     252           0 :         if( pAttr && nStart == pAttr->GetStart() )
     253             :         {
     254           0 :             pPos->nContent = nStart;
     255           0 :             if( !rPam.HasMark() )
     256             :             {
     257           0 :                 rPam.SetMark();
     258           0 :                 pPos->nContent = *pAttr->GetAnyEnd();
     259           0 :                 if( pPos->nContent.GetIndex() > nEnd )
     260           0 :                     pPos->nContent = nEnd;
     261           0 :                 rEntry.SetRubyAttr( pAttr->GetRuby() );
     262             :             }
     263           0 :             break;
     264             :         }
     265             : 
     266           0 :         sal_Int32 nChType = rCC.getType(rText, nStart);
     267           0 :         bool bIgnoreChar = false, bIsAlphaNum = false, bChkNxtWrd = false;
     268           0 :         switch( nChType )
     269             :         {
     270             :         case UnicodeType::UPPERCASE_LETTER:
     271             :         case UnicodeType::LOWERCASE_LETTER:
     272             :         case UnicodeType::TITLECASE_LETTER:
     273             :         case UnicodeType::DECIMAL_DIGIT_NUMBER:
     274           0 :                 bChkNxtWrd = bIsAlphaNum = true;
     275           0 :                 break;
     276             : 
     277             :         case UnicodeType::SPACE_SEPARATOR:
     278             :         case UnicodeType::CONTROL:
     279             : /*??*/  case UnicodeType::PRIVATE_USE:
     280             :         case UnicodeType::START_PUNCTUATION:
     281             :         case UnicodeType::END_PUNCTUATION:
     282           0 :             bIgnoreChar = true;
     283           0 :             break;
     284             : 
     285             :         case UnicodeType::OTHER_LETTER:
     286           0 :             bChkNxtWrd = true;
     287             :             //fall-through
     288             :         default:
     289           0 :                 bIsAlphaNum = false;
     290           0 :                 break;
     291             :         }
     292             : 
     293           0 :         if( rPam.HasMark() )
     294             :         {
     295           0 :             if( bIgnoreChar || bIsAlphaNum != bAlphaNum || nStart >= nWordEnd )
     296             :                 break;
     297             :         }
     298           0 :         else if( !bIgnoreChar )
     299             :         {
     300           0 :             rPam.SetMark();
     301           0 :             bAlphaNum = bIsAlphaNum;
     302           0 :             if( bChkNxtWrd && g_pBreakIt->GetBreakIter().is() )
     303             :             {
     304             :                 // search the end of this word
     305           0 :                 nWordEnd = g_pBreakIt->GetBreakIter()->getWordBoundary(
     306             :                             rText, nStart,
     307           0 :                             g_pBreakIt->GetLocale( pTNd->GetLang( nStart )),
     308             :                             WordType::ANYWORD_IGNOREWHITESPACES,
     309           0 :                             true ).endPos;
     310           0 :                 if( 0 > nWordEnd || nWordEnd > nEnd || nWordEnd == nStart )
     311           0 :                     nWordEnd = nEnd;
     312             :             }
     313             :         }
     314           0 :         pTNd->GoNext( &pPos->nContent, CRSR_SKIP_CHARS );
     315           0 :         nStart = pPos->nContent.GetIndex();
     316             :     }
     317             : 
     318           0 :     nStart = rPam.GetMark()->nContent.GetIndex();
     319             :     rEntry.SetText( rText.copy( nStart,
     320           0 :                            rPam.GetPoint()->nContent.GetIndex() - nStart ));
     321           0 :     return rPam.HasMark();
     322             : }
     323             : 
     324           0 : SwRubyListEntry::~SwRubyListEntry()
     325             : {
     326         177 : }
     327             : 
     328             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11