LCOV - code coverage report
Current view: top level - libreoffice/sw/source/core/txtnode - ndhints.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 72 79 91.1 %
Date: 2012-12-17 Functions: 8 8 100.0 %
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             : 
      21             : #include "txatbase.hxx"
      22             : #include "ndhints.hxx"
      23             : #include <txtatr.hxx>
      24             : 
      25             : #ifdef DBG_UTIL
      26             : #include <pam.hxx>
      27             : #endif
      28             : 
      29             : 
      30             : inline void DumpHints(const SwpHtStart &, const SwpHtEnd &) { }
      31             : 
      32             : /*************************************************************************
      33             :  *                      IsLessStart()
      34             :  *************************************************************************/
      35             : 
      36             : // Sortierreihenfolge: Start, Ende (umgekehrt!), Which-Wert (umgekehrt!),
      37             : //                     als letztes die Adresse selbst
      38             : 
      39      765150 : static bool lcl_IsLessStart( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
      40             : {
      41      765150 :     if ( *rHt1.GetStart() == *rHt2.GetStart() )
      42             :     {
      43       36058 :         const xub_StrLen nHt1 = *rHt1.GetAnyEnd();
      44       36058 :         const xub_StrLen nHt2 = *rHt2.GetAnyEnd();
      45       36058 :         if ( nHt1 == nHt2 )
      46             :         {
      47       35132 :             const sal_uInt16 nWhich1 = rHt1.Which();
      48       35132 :             const sal_uInt16 nWhich2 = rHt2.Which();
      49       35132 :             if ( nWhich1 == nWhich2 )
      50             :             {
      51       35030 :                 if ( RES_TXTATR_CHARFMT == nWhich1 )
      52             :                 {
      53           0 :                     const sal_uInt16 nS1 = static_cast<const SwTxtCharFmt&>(rHt1).GetSortNumber();
      54           0 :                     const sal_uInt16 nS2 = static_cast<const SwTxtCharFmt&>(rHt2).GetSortNumber();
      55           0 :                     if ( nS1 != nS2 ) // robust
      56           0 :                         return nS1 < nS2;
      57             :                 }
      58             : 
      59       35030 :                 return (long)&rHt1 < (long)&rHt2;
      60             :             }
      61             :             // order is important! for requirements see hintids.hxx
      62         102 :             return ( nWhich1 > nWhich2 );
      63             :         }
      64         926 :         return ( nHt1 > nHt2 );
      65             :     }
      66      729092 :     return ( *rHt1.GetStart() < *rHt2.GetStart() );
      67             : }
      68             : 
      69             : /*************************************************************************
      70             :  *                      inline IsLessEnd()
      71             :  *************************************************************************/
      72             : 
      73             : // Zuerst nach Ende danach nach Ptr
      74      781774 : static bool lcl_IsLessEnd( const SwTxtAttr &rHt1, const SwTxtAttr &rHt2 )
      75             : {
      76      781774 :     const xub_StrLen nHt1 = *rHt1.GetAnyEnd();
      77      781774 :     const xub_StrLen nHt2 = *rHt2.GetAnyEnd();
      78      781774 :     if ( nHt1 == nHt2 )
      79             :     {
      80       39968 :         if ( *rHt1.GetStart() == *rHt2.GetStart() )
      81             :         {
      82       38260 :             const sal_uInt16 nWhich1 = rHt1.Which();
      83       38260 :             const sal_uInt16 nWhich2 = rHt2.Which();
      84       38260 :             if ( nWhich1 == nWhich2 )
      85             :             {
      86       38086 :                 if ( RES_TXTATR_CHARFMT == nWhich1 )
      87             :                 {
      88          16 :                     const sal_uInt16 nS1 = static_cast<const SwTxtCharFmt&>(rHt1).GetSortNumber();
      89          16 :                     const sal_uInt16 nS2 = static_cast<const SwTxtCharFmt&>(rHt2).GetSortNumber();
      90          16 :                     if ( nS1 != nS2 ) // robust
      91           0 :                         return nS1 > nS2;
      92             :                 }
      93             : 
      94       38086 :                 return (long)&rHt1 > (long)&rHt2;
      95             :             }
      96             :             // order is important! for requirements see hintids.hxx
      97         174 :             return ( nWhich1 < nWhich2 );
      98             :         }
      99             :         else
     100        1708 :             return ( *rHt1.GetStart() > *rHt2.GetStart() );
     101             :     }
     102      741806 :     return ( nHt1 < nHt2 );
     103             : }
     104             : 
     105      117342 : bool CompareSwpHtStart::operator()(SwTxtAttr* const lhs, SwTxtAttr* const rhs) const
     106             : {
     107      117342 :   return lcl_IsLessStart( *lhs, *rhs );
     108             : }
     109             : 
     110      120666 : bool CompareSwpHtEnd::operator()(SwTxtAttr* const lhs, SwTxtAttr* const rhs) const
     111             : {
     112      120666 :   return lcl_IsLessEnd( *lhs, *rhs );
     113             : }
     114             : 
     115             : /*************************************************************************
     116             :  *                      class SwpHintsArr
     117             :  *************************************************************************/
     118             : 
     119       25485 : void SwpHintsArray::Insert( const SwTxtAttr *pHt )
     120             : {
     121       25485 :     Resort();
     122             :     assert(m_HintStarts.find(const_cast<SwTxtAttr*>(pHt))
     123             :             == m_HintStarts.end()); // "Insert: hint already in HtStart"
     124             :     assert(m_HintEnds.find(const_cast<SwTxtAttr*>(pHt))
     125             :             == m_HintEnds.end());   // "Insert: hint already in HtEnd"
     126       25485 :     m_HintStarts.insert( const_cast<SwTxtAttr*>(pHt) );
     127       25485 :     m_HintEnds  .insert( const_cast<SwTxtAttr*>(pHt) );
     128       25485 : }
     129             : 
     130       19038 : void SwpHintsArray::DeleteAtPos( const sal_uInt16 nPos )
     131             : {
     132             :     // optimization: nPos is the position in the Starts array
     133       19038 :     SwTxtAttr *pHt = m_HintStarts[ nPos ];
     134       19038 :     m_HintStarts.erase( m_HintStarts.begin() + nPos );
     135             : 
     136       19038 :     Resort();
     137             : 
     138       19038 :     bool const done = m_HintEnds.erase(pHt);
     139             :     assert(done);
     140             :     (void) done; // unused in NDEBUG
     141       19038 : }
     142             : 
     143         442 : sal_uInt16 SwpHintsArray::GetPos( const SwTxtAttr *pHt ) const
     144             : {
     145             :     // DO NOT use find() here!
     146             :     // if called from SwTxtNode::InsertItem, pHt has already been deleted,
     147             :     // so it cannot be dereferenced
     148         686 :     for (size_t i = 0; i < m_HintStarts.size(); ++i)
     149             :     {
     150         684 :         if (m_HintStarts[i] == pHt)
     151             :         {
     152         440 :             return i;
     153             :         }
     154             :     }
     155           2 :     return USHRT_MAX;
     156             : }
     157             : 
     158             : #ifdef DBG_UTIL
     159             : 
     160             : /*************************************************************************
     161             :  *                      SwpHintsArray::Check()
     162             :  *************************************************************************/
     163             : 
     164             : 
     165             : #define CHECK_ERR(cond, text) \
     166             :         if(!(cond)) \
     167             :         { \
     168             :             SAL_WARN("sw.core", text); \
     169             :             DumpHints(m_HintStarts, m_HintEnds); \
     170             :             return !(const_cast<SwpHintsArray*>(this))->Resort(); \
     171             :         }
     172             : 
     173             : bool SwpHintsArray::Check() const
     174             : {
     175             :     // 1) gleiche Anzahl in beiden Arrays
     176             :     CHECK_ERR( m_HintStarts.size() == m_HintEnds.size(),
     177             :         "HintsCheck: wrong sizes" );
     178             :     xub_StrLen nLastStart = 0;
     179             :     xub_StrLen nLastEnd   = 0;
     180             : 
     181             :     const SwTxtAttr *pLastStart = 0;
     182             :     const SwTxtAttr *pLastEnd = 0;
     183             : 
     184             :     for( sal_uInt16 i = 0; i < Count(); ++i )
     185             :     {
     186             :         // --- Start-Kontrolle ---
     187             : 
     188             :         // 2a) gueltiger Pointer? vgl. DELETEFF
     189             :         const SwTxtAttr *pHt = m_HintStarts[i];
     190             :         CHECK_ERR( 0xFF != *(unsigned char*)pHt, "HintsCheck: start ptr was deleted" );
     191             : 
     192             :         // 3a) Stimmt die Start-Sortierung?
     193             :         xub_StrLen nIdx = *pHt->GetStart();
     194             :         CHECK_ERR( nIdx >= nLastStart, "HintsCheck: starts are unsorted" );
     195             : 
     196             :         // 4a) IsLessStart-Konsistenz
     197             :         if( pLastStart )
     198             :             CHECK_ERR( lcl_IsLessStart( *pLastStart, *pHt ), "HintsCheck: IsLastStart" );
     199             : 
     200             :         nLastStart = nIdx;
     201             :         pLastStart = pHt;
     202             : 
     203             :         // --- End-Kontrolle ---
     204             : 
     205             :         // 2b) gueltiger Pointer? vgl. DELETEFF
     206             :         const SwTxtAttr *pHtEnd = m_HintEnds[i];
     207             :         CHECK_ERR( 0xFF != *(unsigned char*)pHtEnd, "HintsCheck: end ptr was deleted" );
     208             : 
     209             :         // 3b) Stimmt die End-Sortierung?
     210             :         nIdx = *pHtEnd->GetAnyEnd();
     211             :         CHECK_ERR( nIdx >= nLastEnd, "HintsCheck: ends are unsorted" );
     212             :         nLastEnd = nIdx;
     213             : 
     214             :         // 4b) IsLessEnd-Konsistenz
     215             :         if( pLastEnd )
     216             :             CHECK_ERR( lcl_IsLessEnd( *pLastEnd, *pHtEnd ), "HintsCheck: IsLastEnd" );
     217             : 
     218             :         nLastEnd = nIdx;
     219             :         pLastEnd = pHtEnd;
     220             : 
     221             :         // --- Ueberkreuzungen ---
     222             : 
     223             :         // 5) gleiche Pointer in beiden Arrays
     224             :         if (m_HintStarts.find(const_cast<SwTxtAttr*>(pHt)) == m_HintStarts.end())
     225             :             nIdx = STRING_LEN;
     226             : 
     227             :         CHECK_ERR( STRING_LEN != nIdx, "HintsCheck: no GetStartOf" );
     228             : 
     229             :         // 6) gleiche Pointer in beiden Arrays
     230             :         if (m_HintEnds.find(const_cast<SwTxtAttr*>(pHt)) == m_HintEnds.end())
     231             :             nIdx = STRING_LEN;
     232             : 
     233             :         CHECK_ERR( STRING_LEN != nIdx, "HintsCheck: no GetEndOf" );
     234             : 
     235             :         // 7a) character attributes in array?
     236             :         sal_uInt16 nWhich = pHt->Which();
     237             :         CHECK_ERR( !isCHRATR(nWhich),
     238             :                    "HintsCheck: Character attribute in start array" );
     239             : 
     240             :         // 7b) character attributes in array?
     241             :         nWhich = pHtEnd->Which();
     242             :         CHECK_ERR( !isCHRATR(nWhich),
     243             :                    "HintsCheck: Character attribute in end array" );
     244             : 
     245             :         // 8) style portion check
     246             :         const SwTxtAttr* pHtThis = m_HintStarts[i];
     247             :         const SwTxtAttr* pHtLast = i > 0 ? m_HintStarts[i-1] : 0;
     248             :         CHECK_ERR( (0 == i)
     249             :             ||  (   (RES_TXTATR_CHARFMT != pHtLast->Which())
     250             :                 &&  (RES_TXTATR_AUTOFMT != pHtLast->Which()))
     251             :             ||  (   (RES_TXTATR_CHARFMT != pHtThis->Which())
     252             :                 &&  (RES_TXTATR_AUTOFMT != pHtThis->Which()))
     253             :             ||  (*pHtThis->GetStart() >= *pHtLast->GetEnd()) // no overlap
     254             :             ||  (   (   (*pHtThis->GetStart() == *pHtLast->GetStart())
     255             :                     &&  (*pHtThis->GetEnd()   == *pHtLast->GetEnd())
     256             :                     ) // same range
     257             :                 &&  (   (pHtThis->Which() != RES_TXTATR_AUTOFMT)
     258             :                     ||  (pHtLast->Which() != RES_TXTATR_AUTOFMT)
     259             :                     ) // never two AUTOFMT on same range
     260             :                 &&  (   (pHtThis->Which() != RES_TXTATR_CHARFMT)
     261             :                     ||  (pHtLast->Which() != RES_TXTATR_CHARFMT)
     262             :                     ||  (static_cast<const SwTxtCharFmt *>(pHtThis)
     263             :                                 ->GetSortNumber() !=
     264             :                          static_cast<const SwTxtCharFmt *>(pHtLast)
     265             :                                 ->GetSortNumber())
     266             :                     ) // multiple CHARFMT on same range need distinct sortnr
     267             :                 )
     268             :             ||  (*pHtThis->GetStart() == *pHtThis->GetEnd()), // this empty
     269             :                    "HintsCheck: Portion inconsistency. "
     270             :                    "This can be temporarily ok during undo operations" );
     271             : 
     272             :         // 9) nesting portion check
     273             :         if (pHtThis->IsNesting())
     274             :         {
     275             :             for ( sal_uInt16 j = 0; j < Count(); ++j )
     276             :             {
     277             :                 SwTxtAttr const * const pOther( m_HintStarts[j] );
     278             :                 if ( pOther->IsNesting() &&  (i != j) )
     279             :                 {
     280             :                     SwComparePosition cmp = ComparePosition(
     281             :                         *pHtThis->GetStart(), *pHtThis->GetEnd(),
     282             :                         *pOther->GetStart(), *pOther->GetEnd());
     283             :                     CHECK_ERR( (POS_OVERLAP_BEFORE != cmp) &&
     284             :                                (POS_OVERLAP_BEHIND != cmp),
     285             :                         "HintsCheck: overlapping nesting hints!!!" );
     286             :                 }
     287             :             }
     288             :         }
     289             : 
     290             :         // 10) dummy char check (unfortunately cannot check SwTxtNode::m_Text)
     291             :         if (pHtThis->HasDummyChar())
     292             :         {
     293             :             for ( sal_uInt16 j = 0; j < i; ++j )
     294             :             {
     295             :                 SwTxtAttr const * const pOther( m_HintStarts[j] );
     296             :                 if (pOther->HasDummyChar())
     297             :                 {
     298             :                     CHECK_ERR( (*pOther->GetStart() != *pHtThis->GetStart()),
     299             :                         "HintsCheck: multiple hints claim same CH_TXTATR!");
     300             :                 }
     301             :             }
     302             :         }
     303             :     }
     304             :     return true;
     305             : }
     306             : 
     307             : #endif      /* DBG_UTIL */
     308             : 
     309             : /*************************************************************************
     310             :  *                          SwpHintsArray::Resort()
     311             :  *************************************************************************/
     312             : 
     313             : // Resort() wird vor jedem Insert und Delete gerufen.
     314             : // Wenn Textmasse geloescht wird, so werden die Indizes in
     315             : // ndtxt.cxx angepasst. Leider erfolgt noch keine Neusortierung
     316             : // auf gleichen Positionen.
     317             : 
     318       66753 : bool SwpHintsArray::Resort()
     319             : {
     320       66753 :     bool bResort = false;
     321       66753 :     const SwTxtAttr *pLast = 0;
     322             :     sal_uInt16 i;
     323             : 
     324      767901 :     for ( i = 0; i < m_HintStarts.size(); ++i )
     325             :     {
     326      701148 :         SwTxtAttr *pHt = m_HintStarts[i];
     327      701148 :         if( pLast && !lcl_IsLessStart( *pLast, *pHt ) )
     328             :         {
     329           4 :             m_HintStarts.erase( m_HintStarts.begin() + i );
     330           4 :             m_HintStarts.insert( pHt );
     331           4 :             pHt = m_HintStarts[i];
     332           4 :             if ( pHt != pLast )
     333           0 :                 --i;
     334           4 :             bResort = true;
     335             :         }
     336      701148 :         pLast = pHt;
     337             :     }
     338             : 
     339       66753 :     pLast = 0;
     340      786939 :     for ( i = 0; i < m_HintEnds.size(); ++i )
     341             :     {
     342      720186 :         SwTxtAttr *pHt = m_HintEnds[i];
     343      720186 :         if( pLast && !lcl_IsLessEnd( *pLast, *pHt ) )
     344             :         {
     345           4 :             m_HintEnds.erase( m_HintEnds.begin() + i );
     346           4 :             m_HintEnds.insert( pHt );
     347           4 :             pHt = m_HintEnds[i]; // normalerweise == pLast
     348             :             // Wenn die Unordnung etwas groesser ist (24200),
     349             :             // muessen wir Position i erneut vergleichen.
     350           4 :             if ( pLast != pHt )
     351           0 :                 --i;
     352           4 :             bResort = true;
     353             :         }
     354      720186 :         pLast = pHt;
     355             :     }
     356       66753 :     return bResort;
     357             : }
     358             : 
     359             : 
     360             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10