1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 32 #include <hintids.hxx> 33 34 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_ 35 #include <com/sun/star/i18n/ScriptType.hdl> 36 #endif 37 #include <tools/string.hxx> 38 #include <editeng/langitem.hxx> 39 #include <txatritr.hxx> 40 #include <fchrfmt.hxx> 41 #include <charfmt.hxx> 42 #include <breakit.hxx> 43 #include <ndtxt.hxx> 44 #include <txatbase.hxx> 45 46 using namespace ::com::sun::star::i18n; 47 48 49 SwScriptIterator::SwScriptIterator( const String& rStr, xub_StrLen nStt, sal_Bool bFrwrd ) 50 : rText( rStr ), 51 nChgPos( rStr.Len() ), 52 nCurScript( ScriptType::WEAK ), 53 bForward( bFrwrd ) 54 { 55 if( pBreakIt->GetBreakIter().is() ) 56 { 57 if ( ! bFrwrd && nStt ) 58 --nStt; 59 60 xub_StrLen nPos = nStt; 61 nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nPos ); 62 if( ScriptType::WEAK == nCurScript ) 63 { 64 if( nPos ) 65 { 66 nPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript( 67 rText, nPos, nCurScript ); 68 if( nPos && nPos < rText.Len() ) 69 { 70 nStt = --nPos; 71 nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText,nPos); 72 } 73 } 74 } 75 76 nChgPos = bForward ? 77 (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( rText, nStt, nCurScript ) : 78 (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript( rText, nStt, nCurScript ); 79 } 80 } 81 82 sal_Bool SwScriptIterator::Next() 83 { 84 sal_Bool bRet = sal_False; 85 if( pBreakIt->GetBreakIter().is() ) 86 { 87 if ( bForward && nChgPos < rText.Len() ) 88 { 89 nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nChgPos ); 90 nChgPos = (xub_StrLen)pBreakIt->GetBreakIter()->endOfScript( 91 rText, nChgPos, nCurScript ); 92 bRet = sal_True; 93 } 94 else if ( ! bForward && nChgPos ) 95 { 96 --nChgPos; 97 nCurScript = pBreakIt->GetBreakIter()->getScriptType( rText, nChgPos ); 98 nChgPos = (xub_StrLen)pBreakIt->GetBreakIter()->beginOfScript( 99 rText, nChgPos, nCurScript ); 100 bRet = sal_True; 101 } 102 } 103 else 104 nChgPos = rText.Len(); 105 return bRet; 106 } 107 108 // -------------------------------------------------------------------- 109 110 SwTxtAttrIterator::SwTxtAttrIterator( const SwTxtNode& rTNd, sal_uInt16 nWhchId, 111 xub_StrLen nStt, 112 sal_Bool bUseGetWhichOfScript ) 113 : aSIter( rTNd.GetTxt(), nStt ), rTxtNd( rTNd ), 114 pParaItem( 0 ), nChgPos( nStt ), nAttrPos( 0 ), nWhichId( nWhchId ), 115 bIsUseGetWhichOfScript( bUseGetWhichOfScript ) 116 { 117 SearchNextChg(); 118 } 119 120 sal_Bool SwTxtAttrIterator::Next() 121 { 122 sal_Bool bRet = sal_False; 123 if( nChgPos < aSIter.GetText().Len() ) 124 { 125 bRet = sal_True; 126 if( aStack.Count() ) 127 { 128 do { 129 const SwTxtAttr* pHt = (SwTxtAttr*)aStack[ 0 ]; 130 sal_uInt16 nEndPos = *pHt->GetEnd(); 131 if( nChgPos >= nEndPos ) 132 aStack.Remove( 0 ); 133 else 134 break; 135 } while( aStack.Count() ); 136 } 137 138 if( aStack.Count() ) 139 { 140 sal_uInt16 nSavePos = nAttrPos; 141 SearchNextChg(); 142 if( aStack.Count() ) 143 { 144 const SwTxtAttr* pHt = (SwTxtAttr*)aStack[ 0 ]; 145 sal_uInt16 nEndPos = *pHt->GetEnd(); 146 if( nChgPos >= nEndPos ) 147 { 148 nChgPos = nEndPos; 149 nAttrPos = nSavePos; 150 151 if( RES_TXTATR_CHARFMT == pHt->Which() ) 152 { 153 sal_uInt16 nWId = bIsUseGetWhichOfScript ? 154 GetWhichOfScript( nWhichId, 155 aSIter.GetCurrScript() ) : nWhichId; 156 pCurItem = &pHt->GetCharFmt().GetCharFmt()->GetFmtAttr(nWId); 157 } 158 else 159 pCurItem = &pHt->GetAttr(); 160 161 aStack.Remove( 0 ); 162 } 163 } 164 } 165 else 166 SearchNextChg(); 167 } 168 return bRet; 169 } 170 171 void SwTxtAttrIterator::AddToStack( const SwTxtAttr& rAttr ) 172 { 173 void* pAdd = (void*)&rAttr; 174 sal_uInt16 nIns = 0, nEndPos = *rAttr.GetEnd(); 175 for( ; nIns < aStack.Count(); ++nIns ) 176 if( *((SwTxtAttr*)aStack[ nIns ] )->GetEnd() > nEndPos ) 177 break; 178 179 aStack.Insert( pAdd, nIns ); 180 } 181 182 void SwTxtAttrIterator::SearchNextChg() 183 { 184 sal_uInt16 nWh = 0; 185 if( nChgPos == aSIter.GetScriptChgPos() ) 186 { 187 aSIter.Next(); 188 pParaItem = 0; 189 nAttrPos = 0; // must be restart at the beginning, because 190 // some attributes can start before or inside 191 // the current scripttype! 192 aStack.Remove( 0, aStack.Count() ); 193 } 194 if( !pParaItem ) 195 { 196 nWh = bIsUseGetWhichOfScript ? 197 GetWhichOfScript( nWhichId, 198 aSIter.GetCurrScript() ) : nWhichId; 199 pParaItem = &rTxtNd.GetSwAttrSet().Get( nWh ); 200 } 201 202 xub_StrLen nStt = nChgPos; 203 nChgPos = aSIter.GetScriptChgPos(); 204 pCurItem = pParaItem; 205 206 const SwpHints* pHts = rTxtNd.GetpSwpHints(); 207 if( pHts ) 208 { 209 if( !nWh ) 210 { 211 nWh = bIsUseGetWhichOfScript ? 212 GetWhichOfScript( nWhichId, 213 aSIter.GetCurrScript() ) : nWhichId; 214 } 215 216 const SfxPoolItem* pItem = 0; 217 for( ; nAttrPos < pHts->Count(); ++nAttrPos ) 218 { 219 const SwTxtAttr* pHt = (*pHts)[ nAttrPos ]; 220 const sal_uInt16* pEnd = pHt->GetEnd(); 221 const sal_uInt16 nHtStt = *pHt->GetStart(); 222 if( nHtStt < nStt && ( !pEnd || *pEnd <= nStt )) 223 continue; 224 225 if( nHtStt >= nChgPos ) 226 break; 227 228 pItem = CharFmt::GetItem( *pHt, nWh ); 229 if ( pItem ) 230 { 231 if( nHtStt > nStt ) 232 { 233 if( nChgPos > nHtStt ) 234 nChgPos = nHtStt; 235 break; 236 } 237 AddToStack( *pHt ); 238 pCurItem = pItem; 239 if( *pEnd < nChgPos ) 240 nChgPos = *pEnd; 241 } 242 } 243 } 244 } 245 246 247