1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_editeng.hxx" 26 #include <tools/debug.hxx> 27 28 #include <editeng/unoedhlp.hxx> 29 #include <editeng/editdata.hxx> 30 #include <editeng/editeng.hxx> 31 #include <svl/itemset.hxx> 32 33 //------------------------------------------------------------------------ 34 35 TYPEINIT1( SvxEditSourceHint, TextHint ); 36 37 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId ) : 38 TextHint( _nId ), 39 mnStart( 0 ), 40 mnEnd( 0 ) 41 { 42 } 43 44 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId, sal_uLong nValue, sal_uLong nStart, sal_uLong nEnd ) : 45 TextHint( _nId, nValue ), 46 mnStart( nStart), 47 mnEnd( nEnd ) 48 { 49 } 50 51 sal_uLong SvxEditSourceHint::GetValue() const 52 { 53 return TextHint::GetValue(); 54 } 55 56 sal_uLong SvxEditSourceHint::GetStartValue() const 57 { 58 return mnStart; 59 } 60 61 sal_uLong SvxEditSourceHint::GetEndValue() const 62 { 63 return mnEnd; 64 } 65 66 void SvxEditSourceHint::SetValue( sal_uLong n ) 67 { 68 TextHint::SetValue( n ); 69 } 70 71 void SvxEditSourceHint::SetStartValue( sal_uLong n ) 72 { 73 mnStart = n; 74 } 75 76 void SvxEditSourceHint::SetEndValue( sal_uLong n ) 77 { 78 mnEnd = n; 79 } 80 TYPEINIT1( SvxEditSourceHintEndPara , SvxEditSourceHint ); 81 //------------------------------------------------------------------------ 82 83 ::std::auto_ptr<SfxHint> SvxEditSourceHelper::EENotification2Hint( EENotify* aNotify ) 84 { 85 if( aNotify ) 86 { 87 switch( aNotify->eNotificationType ) 88 { 89 case EE_NOTIFY_TEXTMODIFIED: 90 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_MODIFIED, aNotify->nParagraph ) ); 91 92 case EE_NOTIFY_PARAGRAPHINSERTED: 93 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_PARAINSERTED, aNotify->nParagraph ) ); 94 95 case EE_NOTIFY_PARAGRAPHREMOVED: 96 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_PARAREMOVED, aNotify->nParagraph ) ); 97 98 case EE_NOTIFY_PARAGRAPHSMOVED: 99 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHint( EDITSOURCE_HINT_PARASMOVED, aNotify->nParagraph, aNotify->nParam1, aNotify->nParam2 ) ); 100 101 case EE_NOTIFY_TEXTHEIGHTCHANGED: 102 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_TEXTHEIGHTCHANGED, aNotify->nParagraph ) ); 103 104 case EE_NOTIFY_TEXTVIEWSCROLLED: 105 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_VIEWSCROLLED ) ); 106 107 case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED: 108 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHint( EDITSOURCE_HINT_SELECTIONCHANGED ) ); 109 110 case EE_NOTIFY_BLOCKNOTIFICATION_START: 111 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_BLOCKNOTIFICATION_START, 0 ) ); 112 113 case EE_NOTIFY_BLOCKNOTIFICATION_END: 114 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_BLOCKNOTIFICATION_END, 0 ) ); 115 116 case EE_NOTIFY_INPUT_START: 117 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_INPUT_START, 0 ) ); 118 119 case EE_NOTIFY_INPUT_END: 120 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_INPUT_END, 0 ) ); 121 case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED_ENDD_PARA: 122 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHintEndPara( EDITSOURCE_HINT_SELECTIONCHANGED ) ); 123 default: 124 DBG_ERROR( "SvxEditSourceHelper::EENotification2Hint unknown notification" ); 125 break; 126 } 127 } 128 129 return ::std::auto_ptr<SfxHint>( new SfxHint() ); 130 } 131 sal_Bool SvxEditSourceHelper::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, const EditEngine& rEE, sal_uInt16 nPara, sal_uInt16 nIndex, sal_Bool bInCell ) 132 { 133 // IA2 CWS introduced bInCell, but also did many other changes here. 134 // Need to verify implementation with AT (IA2 and ATK) 135 // Old implementation at the end of the method for reference... 136 137 #if 1 138 //added dummy attributes for the default text 139 EECharAttribArray aCharAttribs, aTempCharAttribs; 140 rEE.GetCharAttribs( nPara, aTempCharAttribs ); 141 if ( aTempCharAttribs.Count() ) 142 { 143 sal_uInt32 nIndex2 = 0; 144 sal_uInt32 nParaLen = rEE.GetTextLen(nPara); 145 for ( sal_uInt16 nAttr = 0; nAttr < aTempCharAttribs.Count(); nAttr++ ) 146 { 147 if ( nIndex2 < aTempCharAttribs[nAttr].nStart ) 148 { 149 EECharAttrib aEEAttr; 150 aEEAttr.nStart = sal_uInt16(nIndex2); 151 aEEAttr.nEnd = aTempCharAttribs[nAttr].nStart; 152 aCharAttribs.Insert( aEEAttr, nAttr ); 153 } 154 nIndex2 = aTempCharAttribs[nAttr].nEnd; 155 aCharAttribs.Insert( aTempCharAttribs[nAttr], aCharAttribs.Count() ); 156 } 157 if ( nIndex2 != nParaLen ) 158 { 159 EECharAttrib aEEAttr; 160 aEEAttr.nStart = sal_uInt16(nIndex2); 161 aEEAttr.nEnd = sal_uInt16(nParaLen); 162 aCharAttribs.Insert( aEEAttr, aCharAttribs.Count() ); 163 } 164 } 165 // find closest index in front of nIndex 166 sal_uInt16 nAttr, nCurrIndex; 167 sal_Int32 nClosestStartIndex; 168 sal_Int32 nClosestStartIndex_s, nClosestStartIndex_e; 169 for( nAttr=0, nClosestStartIndex_s=0, nClosestStartIndex_e=0; nAttr<aCharAttribs.Count(); ++nAttr ) 170 { 171 nCurrIndex = aCharAttribs[nAttr].nStart; 172 173 //if( nCurrIndex > nIndex ) 174 // break; // aCharAttribs array is sorted in increasing order for nStart values 175 176 if( nCurrIndex > nClosestStartIndex_s && 177 nCurrIndex <= nIndex) 178 { 179 nClosestStartIndex_s = nCurrIndex; 180 } 181 nCurrIndex = aCharAttribs[nAttr].nEnd; 182 if ( nCurrIndex > nClosestStartIndex_e && 183 nCurrIndex < nIndex ) 184 { 185 nClosestStartIndex_e = nCurrIndex; 186 } 187 } 188 nClosestStartIndex = nClosestStartIndex_s > nClosestStartIndex_e ? nClosestStartIndex_s : nClosestStartIndex_e; 189 190 // find closest index behind of nIndex 191 sal_Int32 nClosestEndIndex; 192 sal_Int32 nClosestEndIndex_s, nClosestEndIndex_e; 193 for( nAttr=0, nClosestEndIndex_s=nClosestEndIndex_e=rEE.GetTextLen(nPara); nAttr<aCharAttribs.Count(); ++nAttr ) 194 { 195 nCurrIndex = aCharAttribs[nAttr].nEnd; 196 197 if( nCurrIndex > nIndex && 198 nCurrIndex < nClosestEndIndex_e ) 199 { 200 nClosestEndIndex_e = nCurrIndex; 201 } 202 nCurrIndex = aCharAttribs[nAttr].nStart; 203 if ( nCurrIndex > nIndex && 204 nCurrIndex < nClosestEndIndex_s) 205 { 206 nClosestEndIndex_s = nCurrIndex; 207 } 208 } 209 nClosestEndIndex = nClosestEndIndex_s < nClosestEndIndex_e ? nClosestEndIndex_s : nClosestEndIndex_e; 210 211 nStartIndex = static_cast<sal_uInt16>( nClosestStartIndex ); 212 nEndIndex = static_cast<sal_uInt16>( nClosestEndIndex ); 213 if ( bInCell ) 214 { 215 EPosition aStartPos( nPara, nStartIndex ), aEndPos( nPara, nEndIndex ); 216 sal_uInt32 nParaCount = rEE.GetParagraphCount(); 217 sal_uInt32 nCrrntParaLen = rEE.GetTextLen(nPara); 218 //need to find closest index in front of nIndex in the previous paragraphs 219 if ( aStartPos.nIndex == 0 ) 220 { 221 SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, 0, 1, GETATTRIBS_CHARATTRIBS ); 222 for ( sal_Int32 nParaIdx = nPara-1; nParaIdx >= 0; nParaIdx-- ) 223 { 224 sal_uInt32 nLen = rEE.GetTextLen( sal_uInt16(nParaIdx) ); 225 if ( nLen ) 226 { 227 sal_uInt16 nStartIdx, nEndIdx; 228 GetAttributeRun( nStartIdx, nEndIdx, rEE, sal_uInt16(nParaIdx), sal_uInt16(nLen), sal_False ); 229 SfxItemSet aSet = rEE.GetAttribs( sal_uInt16(nParaIdx), sal_uInt16(nLen-1), sal_uInt16(nLen), GETATTRIBS_CHARATTRIBS ); 230 if ( aSet == aCrrntSet ) 231 { 232 aStartPos.nPara = sal_uInt16(nParaIdx); 233 aStartPos.nIndex = nStartIdx; 234 if ( aStartPos.nIndex != 0 ) 235 { 236 break; 237 } 238 } 239 } 240 } 241 } 242 //need find closest index behind nIndex in the following paragrphs 243 if ( aEndPos.nIndex == nCrrntParaLen ) 244 { 245 SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, sal_uInt16(nCrrntParaLen-1), sal_uInt16(nCrrntParaLen), GETATTRIBS_CHARATTRIBS ); 246 for ( sal_uInt32 nParaIdx = nPara+1; nParaIdx < nParaCount; nParaIdx++ ) 247 { 248 sal_uInt32 nLen = rEE.GetTextLen( sal_uInt16(nParaIdx) ); 249 if ( nLen ) 250 { 251 sal_uInt16 nStartIdx, nEndIdx; 252 GetAttributeRun( nStartIdx, nEndIdx, rEE, sal_uInt16(nParaIdx), 0, sal_False ); 253 SfxItemSet aSet = rEE.GetAttribs( sal_uInt16(nParaIdx), 0, 1, GETATTRIBS_CHARATTRIBS ); 254 if ( aSet == aCrrntSet ) 255 { 256 aEndPos.nPara = sal_uInt16(nParaIdx); 257 aEndPos.nIndex = nEndIdx; 258 if ( aEndPos.nIndex != nLen ) 259 { 260 break; 261 } 262 } 263 } 264 } 265 } 266 nStartIndex = 0; 267 if ( aStartPos.nPara > 0 ) 268 { 269 for ( sal_uInt16 i = 0; i < aStartPos.nPara; i++ ) 270 { 271 nStartIndex += rEE.GetTextLen(i)+1; 272 } 273 } 274 nStartIndex += aStartPos.nIndex; 275 nEndIndex = 0; 276 if ( aEndPos.nPara > 0 ) 277 { 278 for ( sal_uInt16 i = 0; i < aEndPos.nPara; i++ ) 279 { 280 nEndIndex += rEE.GetTextLen(i)+1; 281 } 282 } 283 nEndIndex += aEndPos.nIndex; 284 } 285 286 return sal_True; 287 288 #else // old implementation 289 290 EECharAttribArray aCharAttribs; 291 292 rEE.GetCharAttribs( nPara, aCharAttribs ); 293 294 // find closest index in front of nIndex 295 sal_uInt16 nAttr, nCurrIndex; 296 sal_Int32 nClosestStartIndex; 297 for( nAttr=0, nClosestStartIndex=0; nAttr<aCharAttribs.Count(); ++nAttr ) 298 { 299 nCurrIndex = aCharAttribs[nAttr].nStart; 300 301 if( nCurrIndex > nIndex ) 302 break; // aCharAttribs array is sorted in increasing order for nStart values 303 304 if( nCurrIndex > nClosestStartIndex ) 305 { 306 nClosestStartIndex = nCurrIndex; 307 } 308 } 309 310 // find closest index behind of nIndex 311 sal_Int32 nClosestEndIndex; 312 for( nAttr=0, nClosestEndIndex=rEE.GetTextLen(nPara); nAttr<aCharAttribs.Count(); ++nAttr ) 313 { 314 nCurrIndex = aCharAttribs[nAttr].nEnd; 315 316 if( nCurrIndex > nIndex && 317 nCurrIndex < nClosestEndIndex ) 318 { 319 nClosestEndIndex = nCurrIndex; 320 } 321 } 322 323 nStartIndex = static_cast<sal_uInt16>( nClosestStartIndex ); 324 nEndIndex = static_cast<sal_uInt16>( nClosestEndIndex ); 325 326 return sal_True; 327 328 #endif 329 } 330 331 Point SvxEditSourceHelper::EEToUserSpace( const Point& rPoint, const Size& rEESize, bool bIsVertical ) 332 { 333 return bIsVertical ? Point( -rPoint.Y() + rEESize.Height(), rPoint.X() ) : rPoint; 334 } 335 336 Point SvxEditSourceHelper::UserSpaceToEE( const Point& rPoint, const Size& rEESize, bool bIsVertical ) 337 { 338 return bIsVertical ? Point( rPoint.Y(), -rPoint.X() + rEESize.Height() ) : rPoint; 339 } 340 341 Rectangle SvxEditSourceHelper::EEToUserSpace( const Rectangle& rRect, const Size& rEESize, bool bIsVertical ) 342 { 343 // #106775# Don't touch rect if not vertical 344 return bIsVertical ? Rectangle( EEToUserSpace(rRect.BottomLeft(), rEESize, bIsVertical), 345 EEToUserSpace(rRect.TopRight(), rEESize, bIsVertical) ) : rRect; 346 } 347 348 Rectangle SvxEditSourceHelper::UserSpaceToEE( const Rectangle& rRect, const Size& rEESize, bool bIsVertical ) 349 { 350 // #106775# Don't touch rect if not vertical 351 return bIsVertical ? Rectangle( UserSpaceToEE(rRect.TopRight(), rEESize, bIsVertical), 352 UserSpaceToEE(rRect.BottomLeft(), rEESize, bIsVertical) ) : rRect; 353 } 354