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 27 #include <vcl/wrkwin.hxx> 28 #include <vcl/dialog.hxx> 29 #include <vcl/msgbox.hxx> 30 #include <vcl/svapp.hxx> 31 32 #include <editeng/tstpitem.hxx> 33 #include <editeng/colritem.hxx> 34 #include <editeng/fontitem.hxx> 35 #include <editeng/crsditem.hxx> 36 #include <editeng/fhgtitem.hxx> 37 #include <editeng/postitem.hxx> 38 #include <editeng/kernitem.hxx> 39 #include <editeng/wrlmitem.hxx> 40 #include <editeng/wghtitem.hxx> 41 #include <editeng/udlnitem.hxx> 42 #include <editeng/cntritem.hxx> 43 #include <editeng/escpitem.hxx> 44 #include <editeng/shdditem.hxx> 45 #include <editeng/akrnitem.hxx> 46 #include <editeng/cscoitem.hxx> 47 #include <editeng/langitem.hxx> 48 #include <editeng/emphitem.hxx> 49 #include <editeng/charscaleitem.hxx> 50 #include <editeng/charreliefitem.hxx> 51 #include <editeng/xmlcnitm.hxx> 52 #include <editeng/editids.hrc> 53 54 #include <editdoc.hxx> 55 #include <editdbg.hxx> 56 #include <editeng/eerdll.hxx> 57 #include <eerdll2.hxx> 58 #include <tools/stream.hxx> 59 #include <tools/debug.hxx> 60 #include <tools/shl.hxx> 61 #include <vcl/svapp.hxx> 62 #include <com/sun/star/i18n/ScriptType.hpp> 63 #include <stdlib.h> // qsort 64 65 using namespace ::com::sun::star; 66 67 68 // ------------------------------------------------------------ 69 70 sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, short nScriptType ) 71 { 72 sal_uInt16 nId = nItemId; 73 74 if ( ( nScriptType == i18n::ScriptType::ASIAN ) || 75 ( nScriptType == i18n::ScriptType::COMPLEX ) ) 76 { 77 switch ( nItemId ) 78 { 79 case EE_CHAR_LANGUAGE: 80 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL; 81 break; 82 case EE_CHAR_FONTINFO: 83 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL; 84 break; 85 case EE_CHAR_FONTHEIGHT: 86 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL; 87 break; 88 case EE_CHAR_WEIGHT: 89 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL; 90 break; 91 case EE_CHAR_ITALIC: 92 nId = ( nScriptType == i18n::ScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL; 93 break; 94 } 95 } 96 97 return nId; 98 } 99 100 sal_Bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType ) 101 { 102 sal_Bool bValid = sal_True; 103 104 switch ( nItemId ) 105 { 106 case EE_CHAR_LANGUAGE: 107 bValid = nScriptType == i18n::ScriptType::LATIN; 108 break; 109 case EE_CHAR_LANGUAGE_CJK: 110 bValid = nScriptType == i18n::ScriptType::ASIAN; 111 break; 112 case EE_CHAR_LANGUAGE_CTL: 113 bValid = nScriptType == i18n::ScriptType::COMPLEX; 114 break; 115 case EE_CHAR_FONTINFO: 116 bValid = nScriptType == i18n::ScriptType::LATIN; 117 break; 118 case EE_CHAR_FONTINFO_CJK: 119 bValid = nScriptType == i18n::ScriptType::ASIAN; 120 break; 121 case EE_CHAR_FONTINFO_CTL: 122 bValid = nScriptType == i18n::ScriptType::COMPLEX; 123 break; 124 case EE_CHAR_FONTHEIGHT: 125 bValid = nScriptType == i18n::ScriptType::LATIN; 126 break; 127 case EE_CHAR_FONTHEIGHT_CJK: 128 bValid = nScriptType == i18n::ScriptType::ASIAN; 129 break; 130 case EE_CHAR_FONTHEIGHT_CTL: 131 bValid = nScriptType == i18n::ScriptType::COMPLEX; 132 break; 133 case EE_CHAR_WEIGHT: 134 bValid = nScriptType == i18n::ScriptType::LATIN; 135 break; 136 case EE_CHAR_WEIGHT_CJK: 137 bValid = nScriptType == i18n::ScriptType::ASIAN; 138 break; 139 case EE_CHAR_WEIGHT_CTL: 140 bValid = nScriptType == i18n::ScriptType::COMPLEX; 141 break; 142 case EE_CHAR_ITALIC: 143 bValid = nScriptType == i18n::ScriptType::LATIN; 144 break; 145 case EE_CHAR_ITALIC_CJK: 146 bValid = nScriptType == i18n::ScriptType::ASIAN; 147 break; 148 case EE_CHAR_ITALIC_CTL: 149 bValid = nScriptType == i18n::ScriptType::COMPLEX; 150 break; 151 } 152 153 return bValid; 154 } 155 156 157 // ------------------------------------------------------------ 158 159 // Sollte spaeter zentral nach TOOLS/STRING (Aktuell: 303) 160 // fuer Grep: WS_TARGET 161 162 DBG_NAME( EE_TextPortion ); 163 DBG_NAME( EE_EditLine ); 164 DBG_NAME( EE_ContentNode ); 165 DBG_NAME( EE_CharAttribList ); 166 167 SfxItemInfo aItemInfos[EDITITEMCOUNT] = { 168 { SID_ATTR_FRAMEDIRECTION, SFX_ITEM_POOLABLE }, // EE_PARA_WRITINGDIR 169 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_XMLATTRIBS 170 { SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEM_POOLABLE }, // EE_PARA_HANGINGPUNCTUATION 171 { SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEM_POOLABLE }, 172 { SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEM_POOLABLE }, // EE_PARA_ASIANCJKSPACING 173 { SID_ATTR_NUMBERING_RULE, SFX_ITEM_POOLABLE }, // EE_PARA_NUMBULL 174 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_HYPHENATE 175 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_BULLETSTATE 176 { 0, SFX_ITEM_POOLABLE }, // EE_PARA_OUTLLRSPACE 177 { SID_ATTR_PARA_OUTLLEVEL, SFX_ITEM_POOLABLE }, 178 { SID_ATTR_PARA_BULLET, SFX_ITEM_POOLABLE }, 179 { SID_ATTR_LRSPACE, SFX_ITEM_POOLABLE }, 180 { SID_ATTR_ULSPACE, SFX_ITEM_POOLABLE }, 181 { SID_ATTR_PARA_LINESPACE, SFX_ITEM_POOLABLE }, 182 { SID_ATTR_PARA_ADJUST, SFX_ITEM_POOLABLE }, 183 { SID_ATTR_TABSTOP, SFX_ITEM_POOLABLE }, 184 { SID_ATTR_CHAR_COLOR, SFX_ITEM_POOLABLE }, 185 { SID_ATTR_CHAR_FONT, SFX_ITEM_POOLABLE }, 186 { SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEM_POOLABLE }, 187 { SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEM_POOLABLE }, 188 { SID_ATTR_CHAR_WEIGHT, SFX_ITEM_POOLABLE }, 189 { SID_ATTR_CHAR_UNDERLINE, SFX_ITEM_POOLABLE }, 190 { SID_ATTR_CHAR_STRIKEOUT, SFX_ITEM_POOLABLE }, 191 { SID_ATTR_CHAR_POSTURE, SFX_ITEM_POOLABLE }, 192 { SID_ATTR_CHAR_CONTOUR, SFX_ITEM_POOLABLE }, 193 { SID_ATTR_CHAR_SHADOWED, SFX_ITEM_POOLABLE }, 194 { SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEM_POOLABLE }, 195 { SID_ATTR_CHAR_AUTOKERN, SFX_ITEM_POOLABLE }, 196 { SID_ATTR_CHAR_KERNING, SFX_ITEM_POOLABLE }, 197 { SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEM_POOLABLE }, 198 { SID_ATTR_CHAR_LANGUAGE, SFX_ITEM_POOLABLE }, 199 { SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEM_POOLABLE }, 200 { SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEM_POOLABLE }, 201 { SID_ATTR_CHAR_CJK_FONT, SFX_ITEM_POOLABLE }, 202 { SID_ATTR_CHAR_CTL_FONT, SFX_ITEM_POOLABLE }, 203 { SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEM_POOLABLE }, 204 { SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEM_POOLABLE }, 205 { SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEM_POOLABLE }, 206 { SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEM_POOLABLE }, 207 { SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEM_POOLABLE }, 208 { SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEM_POOLABLE }, 209 { SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEM_POOLABLE }, 210 { SID_ATTR_CHAR_RELIEF, SFX_ITEM_POOLABLE }, 211 { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_RUBI_DUMMY 212 { 0, SFX_ITEM_POOLABLE }, // EE_CHAR_XMLATTRIBS 213 { SID_ATTR_CHAR_OVERLINE, SFX_ITEM_POOLABLE }, 214 { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_TAB 215 { 0, SFX_ITEM_POOLABLE }, // EE_FEATURE_LINEBR 216 { SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEM_POOLABLE }, // EE_FEATURE_NOTCONV 217 { SID_FIELD, SFX_ITEM_POOLABLE } 218 }; 219 220 sal_uInt16 aV1Map[] = { 221 3999, 4001, 4002, 4003, 4004, 4005, 4006, 222 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4017, 4018, 4019 // MI: 4019? 223 }; 224 225 sal_uInt16 aV2Map[] = { 226 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 227 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4018, 4019, 4020 228 }; 229 230 sal_uInt16 aV3Map[] = { 231 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 232 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 233 4020, 4021 234 }; 235 236 sal_uInt16 aV4Map[] = { 237 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 238 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 239 4014, 4015, 4016, 4017, 4018, 240 /* CJK Items inserted here: EE_CHAR_LANGUAGE - EE_CHAR_XMLATTRIBS */ 241 4034, 4035, 4036, 4037 242 }; 243 244 sal_uInt16 aV5Map[] = { 245 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 246 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 247 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 248 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 249 /* EE_CHAR_OVERLINE inserted here */ 250 4035, 4036, 4037, 4038 251 }; 252 253 int SAL_CALL CompareStart( const void* pFirst, const void* pSecond ) 254 { 255 if ( (*((EditCharAttrib**)pFirst))->GetStart() < (*((EditCharAttrib**)pSecond))->GetStart() ) 256 return (-1); 257 else if ( (*((EditCharAttrib**)pFirst))->GetStart() > (*((EditCharAttrib**)pSecond))->GetStart() ) 258 return (1); 259 return 0; 260 } 261 262 EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_uInt16 nS, sal_uInt16 nE ) 263 { 264 // das neue Attribut im Pool anlegen 265 const SfxPoolItem& rNew = rPool.Put( rAttr ); 266 267 EditCharAttrib* pNew = 0; 268 switch( rNew.Which() ) 269 { 270 case EE_CHAR_LANGUAGE: 271 case EE_CHAR_LANGUAGE_CJK: 272 case EE_CHAR_LANGUAGE_CTL: 273 { 274 pNew = new EditCharAttribLanguage( (const SvxLanguageItem&)rNew, nS, nE ); 275 } 276 break; 277 case EE_CHAR_COLOR: 278 { 279 pNew = new EditCharAttribColor( (const SvxColorItem&)rNew, nS, nE ); 280 } 281 break; 282 case EE_CHAR_FONTINFO: 283 case EE_CHAR_FONTINFO_CJK: 284 case EE_CHAR_FONTINFO_CTL: 285 { 286 pNew = new EditCharAttribFont( (const SvxFontItem&)rNew, nS, nE ); 287 } 288 break; 289 case EE_CHAR_FONTHEIGHT: 290 case EE_CHAR_FONTHEIGHT_CJK: 291 case EE_CHAR_FONTHEIGHT_CTL: 292 { 293 pNew = new EditCharAttribFontHeight( (const SvxFontHeightItem&)rNew, nS, nE ); 294 } 295 break; 296 case EE_CHAR_FONTWIDTH: 297 { 298 pNew = new EditCharAttribFontWidth( (const SvxCharScaleWidthItem&)rNew, nS, nE ); 299 } 300 break; 301 case EE_CHAR_WEIGHT: 302 case EE_CHAR_WEIGHT_CJK: 303 case EE_CHAR_WEIGHT_CTL: 304 { 305 pNew = new EditCharAttribWeight( (const SvxWeightItem&)rNew, nS, nE ); 306 } 307 break; 308 case EE_CHAR_UNDERLINE: 309 { 310 pNew = new EditCharAttribUnderline( (const SvxUnderlineItem&)rNew, nS, nE ); 311 } 312 break; 313 case EE_CHAR_OVERLINE: 314 { 315 pNew = new EditCharAttribOverline( (const SvxOverlineItem&)rNew, nS, nE ); 316 } 317 break; 318 case EE_CHAR_EMPHASISMARK: 319 { 320 pNew = new EditCharAttribEmphasisMark( (const SvxEmphasisMarkItem&)rNew, nS, nE ); 321 } 322 break; 323 case EE_CHAR_RELIEF: 324 { 325 pNew = new EditCharAttribRelief( (const SvxCharReliefItem&)rNew, nS, nE ); 326 } 327 break; 328 case EE_CHAR_STRIKEOUT: 329 { 330 pNew = new EditCharAttribStrikeout( (const SvxCrossedOutItem&)rNew, nS, nE ); 331 } 332 break; 333 case EE_CHAR_ITALIC: 334 case EE_CHAR_ITALIC_CJK: 335 case EE_CHAR_ITALIC_CTL: 336 { 337 pNew = new EditCharAttribItalic( (const SvxPostureItem&)rNew, nS, nE ); 338 } 339 break; 340 case EE_CHAR_OUTLINE: 341 { 342 pNew = new EditCharAttribOutline( (const SvxContourItem&)rNew, nS, nE ); 343 } 344 break; 345 case EE_CHAR_SHADOW: 346 { 347 pNew = new EditCharAttribShadow( (const SvxShadowedItem&)rNew, nS, nE ); 348 } 349 break; 350 case EE_CHAR_ESCAPEMENT: 351 { 352 pNew = new EditCharAttribEscapement( (const SvxEscapementItem&)rNew, nS, nE ); 353 } 354 break; 355 case EE_CHAR_PAIRKERNING: 356 { 357 pNew = new EditCharAttribPairKerning( (const SvxAutoKernItem&)rNew, nS, nE ); 358 } 359 break; 360 case EE_CHAR_KERNING: 361 { 362 pNew = new EditCharAttribKerning( (const SvxKerningItem&)rNew, nS, nE ); 363 } 364 break; 365 case EE_CHAR_WLM: 366 { 367 pNew = new EditCharAttribWordLineMode( (const SvxWordLineModeItem&)rNew, nS, nE ); 368 } 369 break; 370 case EE_CHAR_XMLATTRIBS: 371 { 372 pNew = new EditCharAttrib( rNew, nS, nE ); // Attrib is only for holding XML information... 373 } 374 break; 375 case EE_FEATURE_TAB: 376 { 377 pNew = new EditCharAttribTab( (const SfxVoidItem&)rNew, nS ); 378 } 379 break; 380 case EE_FEATURE_LINEBR: 381 { 382 pNew = new EditCharAttribLineBreak( (const SfxVoidItem&)rNew, nS ); 383 } 384 break; 385 case EE_FEATURE_FIELD: 386 { 387 pNew = new EditCharAttribField( (const SvxFieldItem&)rNew, nS ); 388 } 389 break; 390 default: 391 { 392 DBG_ERROR( "Ungueltiges Attribut!" ); 393 } 394 } 395 return pNew; 396 } 397 398 // ------------------------------------------------------------------------- 399 // class EditLine 400 // ------------------------------------------------------------------------- 401 402 EditLine::EditLine() 403 { 404 DBG_CTOR( EE_EditLine, 0 ); 405 406 nStart = nEnd = 0; 407 nStartPortion = 0; // damit in ungueltiger Zeile ohne Portions von einer gueltigen Zeile mit der Portion Nr0 unterscieden werden kann. 408 nEndPortion = 0; 409 nHeight = 0; 410 nStartPosX = 0; 411 nTxtHeight = 0; 412 nTxtWidth = 0; 413 nCrsrHeight = 0; 414 nMaxAscent = 0; 415 bHangingPunctuation = sal_False; 416 bInvalid = sal_True; 417 } 418 419 EditLine::EditLine( const EditLine& r ) 420 { 421 DBG_CTOR( EE_EditLine, 0 ); 422 423 nEnd = r.nEnd; 424 nStart = r.nStart; 425 nStartPortion = r.nStartPortion; 426 nEndPortion = r.nEndPortion; 427 bHangingPunctuation = r.bHangingPunctuation; 428 429 nHeight = 0; 430 nStartPosX = 0; 431 nTxtHeight = 0; 432 nTxtWidth = 0; 433 nCrsrHeight = 0; 434 nMaxAscent = 0; 435 bInvalid = sal_True; 436 } 437 438 EditLine::~EditLine() 439 { 440 DBG_DTOR( EE_EditLine, 0 ); 441 } 442 443 EditLine* EditLine::Clone() const 444 { 445 EditLine* pL = new EditLine; 446 if ( aPositions.Count() ) 447 { 448 pL->aPositions.Insert (aPositions.GetData(), aPositions.Count(), 0); 449 } 450 pL->nStartPosX = nStartPosX; 451 pL->nStart = nStart; 452 pL->nEnd = nEnd; 453 pL->nStartPortion = nStartPortion; 454 pL->nEndPortion = nEndPortion; 455 pL->nHeight = nHeight; 456 pL->nTxtWidth = nTxtWidth; 457 pL->nTxtHeight = nTxtHeight; 458 pL->nCrsrHeight = nCrsrHeight; 459 pL->nMaxAscent = nMaxAscent; 460 461 return pL; 462 } 463 464 sal_Bool operator == ( const EditLine& r1, const EditLine& r2 ) 465 { 466 if ( r1.nStart != r2.nStart ) 467 return sal_False; 468 469 if ( r1.nEnd != r2.nEnd ) 470 return sal_False; 471 472 if ( r1.nStartPortion != r2.nStartPortion ) 473 return sal_False; 474 475 if ( r1.nEndPortion != r2.nEndPortion ) 476 return sal_False; 477 478 return sal_True; 479 } 480 481 EditLine& EditLine::operator = ( const EditLine& r ) 482 { 483 nEnd = r.nEnd; 484 nStart = r.nStart; 485 nEndPortion = r.nEndPortion; 486 nStartPortion = r.nStartPortion; 487 return *this; 488 } 489 490 491 sal_Bool operator != ( const EditLine& r1, const EditLine& r2 ) 492 { 493 return !( r1 == r2 ); 494 } 495 496 Size EditLine::CalcTextSize( ParaPortion& rParaPortion ) 497 { 498 Size aSz; 499 Size aTmpSz; 500 TextPortion* pPortion; 501 502 sal_uInt16 nIndex = GetStart(); 503 504 DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize vor CreatePortions !" ); 505 506 for ( sal_uInt16 n = nStartPortion; n <= nEndPortion; n++ ) 507 { 508 pPortion = rParaPortion.GetTextPortions().GetObject(n); 509 switch ( pPortion->GetKind() ) 510 { 511 case PORTIONKIND_TEXT: 512 case PORTIONKIND_FIELD: 513 case PORTIONKIND_HYPHENATOR: 514 { 515 aTmpSz = pPortion->GetSize(); 516 aSz.Width() += aTmpSz.Width(); 517 if ( aSz.Height() < aTmpSz.Height() ) 518 aSz.Height() = aTmpSz.Height(); 519 } 520 break; 521 case PORTIONKIND_TAB: 522 // case PORTIONKIND_EXTRASPACE: 523 { 524 aSz.Width() += pPortion->GetSize().Width(); 525 } 526 break; 527 } 528 nIndex = nIndex + pPortion->GetLen(); 529 } 530 531 SetHeight( (sal_uInt16)aSz.Height() ); 532 return aSz; 533 } 534 535 // ------------------------------------------------------------------------- 536 // class EditLineList 537 // ------------------------------------------------------------------------- 538 EditLineList::EditLineList() 539 { 540 } 541 542 EditLineList::~EditLineList() 543 { 544 Reset(); 545 } 546 547 void EditLineList::Reset() 548 { 549 for ( sal_uInt16 nLine = 0; nLine < Count(); nLine++ ) 550 delete GetObject(nLine); 551 Remove( 0, Count() ); 552 } 553 554 void EditLineList::DeleteFromLine( sal_uInt16 nDelFrom ) 555 { 556 DBG_ASSERT( nDelFrom <= (Count() - 1), "DeleteFromLine: Out of range" ); 557 for ( sal_uInt16 nL = nDelFrom; nL < Count(); nL++ ) 558 delete GetObject(nL); 559 Remove( nDelFrom, Count()-nDelFrom ); 560 } 561 562 sal_uInt16 EditLineList::FindLine( sal_uInt16 nChar, sal_Bool bInclEnd ) 563 { 564 for ( sal_uInt16 nLine = 0; nLine < Count(); nLine++ ) 565 { 566 EditLine* pLine = GetObject( nLine ); 567 if ( ( bInclEnd && ( pLine->GetEnd() >= nChar ) ) || 568 ( pLine->GetEnd() > nChar ) ) 569 { 570 return nLine; 571 } 572 } 573 574 DBG_ASSERT( !bInclEnd, "Zeile nicht gefunden: FindLine" ); 575 return ( Count() - 1 ); 576 } 577 578 // ------------------------------------------------------------------------- 579 // class EditSelection 580 // ------------------------------------------------------------------------- 581 sal_Bool EditPaM::DbgIsBuggy( EditDoc& rDoc ) 582 { 583 if ( !pNode ) 584 return sal_True; 585 if ( rDoc.GetPos( pNode ) >= rDoc.Count() ) 586 return sal_True; 587 if ( nIndex > pNode->Len() ) 588 return sal_True; 589 590 return sal_False; 591 } 592 593 sal_Bool EditSelection::DbgIsBuggy( EditDoc& rDoc ) 594 { 595 if ( aStartPaM.DbgIsBuggy( rDoc ) ) 596 return sal_True; 597 if ( aEndPaM.DbgIsBuggy( rDoc ) ) 598 return sal_True; 599 600 return sal_False; 601 } 602 603 EditSelection::EditSelection() 604 { 605 } 606 607 EditSelection::EditSelection( const EditPaM& rStartAndAnd ) 608 { 609 // koennte noch optimiert werden! 610 // nicht erst Def-CTOR vom PaM rufen! 611 aStartPaM = rStartAndAnd; 612 aEndPaM = rStartAndAnd; 613 } 614 615 EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) 616 { 617 // koennte noch optimiert werden! 618 aStartPaM = rStart; 619 aEndPaM = rEnd; 620 } 621 622 EditSelection& EditSelection::operator = ( const EditPaM& rPaM ) 623 { 624 aStartPaM = rPaM; 625 aEndPaM = rPaM; 626 return *this; 627 } 628 629 sal_Bool EditSelection::IsInvalid() const 630 { 631 EditPaM aEmptyPaM; 632 633 if ( aStartPaM == aEmptyPaM ) 634 return sal_True; 635 636 if ( aEndPaM == aEmptyPaM ) 637 return sal_True; 638 639 return sal_False; 640 } 641 642 sal_Bool EditSelection::Adjust( const ContentList& rNodes ) 643 { 644 DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index im Wald in Adjust(1)" ); 645 DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index im Wald in Adjust(2)" ); 646 647 ContentNode* pStartNode = aStartPaM.GetNode(); 648 ContentNode* pEndNode = aEndPaM.GetNode(); 649 650 sal_uInt16 nStartNode = rNodes.GetPos( pStartNode ); 651 sal_uInt16 nEndNode = rNodes.GetPos( pEndNode ); 652 653 DBG_ASSERT( nStartNode != USHRT_MAX, "Node im Wald in Adjust(1)" ); 654 DBG_ASSERT( nEndNode != USHRT_MAX, "Node im Wald in Adjust(2)" ); 655 656 sal_Bool bSwap = sal_False; 657 if ( nStartNode > nEndNode ) 658 bSwap = sal_True; 659 else if ( ( nStartNode == nEndNode ) && ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) ) 660 bSwap = sal_True; 661 662 if ( bSwap ) 663 { 664 EditPaM aTmpPaM( aStartPaM ); 665 aStartPaM = aEndPaM; 666 aEndPaM = aTmpPaM; 667 } 668 669 return bSwap; 670 } 671 672 673 // ------------------------------------------------------------------------- 674 // class EditPaM 675 // ------------------------------------------------------------------------- 676 sal_Bool operator == ( const EditPaM& r1, const EditPaM& r2 ) 677 { 678 if ( r1.GetNode() != r2.GetNode() ) 679 return sal_False; 680 681 if ( r1.GetIndex() != r2.GetIndex() ) 682 return sal_False; 683 684 return sal_True; 685 } 686 687 EditPaM& EditPaM::operator = ( const EditPaM& rPaM ) 688 { 689 nIndex = rPaM.nIndex; 690 pNode = rPaM.pNode; 691 return *this; 692 } 693 694 sal_Bool operator != ( const EditPaM& r1, const EditPaM& r2 ) 695 { 696 return !( r1 == r2 ); 697 } 698 699 700 // ------------------------------------------------------------------------- 701 // class ContentNode 702 // ------------------------------------------------------------------------- 703 ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool ) 704 { 705 DBG_CTOR( EE_ContentNode, 0 ); 706 pWrongList = NULL; 707 } 708 709 ContentNode::ContentNode( const XubString& rStr, const ContentAttribs& rContentAttribs ) : 710 XubString( rStr ), aContentAttribs( rContentAttribs ) 711 { 712 DBG_CTOR( EE_ContentNode, 0 ); 713 pWrongList = NULL; 714 } 715 716 ContentNode::~ContentNode() 717 { 718 DBG_DTOR( EE_ContentNode, 0 ); 719 #ifndef SVX_LIGHT 720 delete pWrongList; 721 #endif 722 } 723 724 void ContentNode::ExpandAttribs( sal_uInt16 nIndex, sal_uInt16 nNew, SfxItemPool& rItemPool ) 725 { 726 if ( !nNew ) 727 return; 728 729 // Da Features anders behandelt werden als normale Zeichenattribute, 730 // kann sich hier auch die Sortierung der Start-Liste aendern! 731 // In jedem if..., in dem weiter (n) Moeglichkeiten aufgrund von 732 // bFeature oder Spezialfall existieren, 733 // muessen (n-1) Moeglichkeiten mit bResort versehen werden. 734 // Die wahrscheinlichste Moeglichkeit erhaelt kein bResort, 735 // so dass nicht neu sortiert wird, wenn sich alle Attribute 736 // gleich verhalten. 737 sal_Bool bResort = sal_False; 738 sal_Bool bExpandedEmptyAtIndexNull = sal_False; 739 740 sal_uInt16 nAttr = 0; 741 EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); 742 while ( pAttrib ) 743 { 744 if ( pAttrib->GetEnd() >= nIndex ) 745 { 746 // Alle Attribute hinter der Einfuegeposition verschieben... 747 if ( pAttrib->GetStart() > nIndex ) 748 { 749 pAttrib->MoveForward( nNew ); 750 } 751 // 0: Leeres Attribut expandieren, wenn an Einfuegestelle 752 else if ( pAttrib->IsEmpty() ) 753 { 754 // Index nicht pruefen, leeres durfte nur dort liegen. 755 // Wenn spaeter doch Ueberpruefung: 756 // Spezialfall: Start == 0; AbsLen == 1, nNew = 1 => Expand, weil durch Absatzumbruch! 757 // Start <= nIndex, End >= nIndex => Start=End=nIndex! 758 // if ( pAttrib->GetStart() == nIndex ) 759 pAttrib->Expand( nNew ); 760 if ( pAttrib->GetStart() == 0 ) 761 bExpandedEmptyAtIndexNull = sal_True; 762 } 763 // 1: Attribut startet davor, geht bis Index... 764 else if ( pAttrib->GetEnd() == nIndex ) // Start muss davor liegen 765 { 766 // Nur expandieren, wenn kein Feature, 767 // und wenn nicht in ExcludeListe! 768 // Sonst geht z.B. ein UL bis zum neuen ULDB, beide expandieren 769 // if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) 770 if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) 771 { 772 if ( !pAttrib->IsEdge() ) 773 pAttrib->Expand( nNew ); 774 } 775 else 776 bResort = sal_True; 777 } 778 // 2: Attribut startet davor, geht hinter Index... 779 else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) 780 { 781 DBG_ASSERT( !pAttrib->IsFeature(), "Grosses Feature?!" ); 782 pAttrib->Expand( nNew ); 783 } 784 // 3: Attribut startet auf Index... 785 else if ( pAttrib->GetStart() == nIndex ) 786 { 787 if ( pAttrib->IsFeature() ) 788 { 789 pAttrib->MoveForward( nNew ); 790 bResort = sal_True; 791 } 792 else 793 { 794 sal_Bool bExpand = sal_False; 795 if ( nIndex == 0 ) 796 { 797 bExpand = sal_True; 798 if( bExpandedEmptyAtIndexNull ) 799 { 800 // Check if this kind of attribut was empty and expanded here... 801 sal_uInt16 nW = pAttrib->GetItem()->Which(); 802 for ( sal_uInt16 nA = 0; nA < nAttr; nA++ ) 803 { 804 EditCharAttrib* pA = aCharAttribList.GetAttribs()[nA]; 805 if ( ( pA->GetStart() == 0 ) && ( pA->GetItem()->Which() == nW ) ) 806 { 807 bExpand = sal_False; 808 break; 809 } 810 } 811 812 } 813 } 814 if ( bExpand ) 815 { 816 pAttrib->Expand( nNew ); 817 bResort = sal_True; 818 } 819 else 820 { 821 pAttrib->MoveForward( nNew ); 822 } 823 } 824 } 825 } 826 827 if ( pAttrib->IsEdge() ) 828 pAttrib->SetEdge( sal_False ); 829 830 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); 831 832 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribut verdreht!" ); 833 DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attrib groesser als Absatz!" ); 834 if ( pAttrib->IsEmpty() ) 835 { 836 DBG_ERROR( "Leeres Attribut nach ExpandAttribs?" ); 837 bResort = sal_True; 838 aCharAttribList.GetAttribs().Remove( nAttr ); 839 rItemPool.Remove( *pAttrib->GetItem() ); 840 delete pAttrib; 841 nAttr--; 842 } 843 nAttr++; 844 pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); 845 } 846 847 if ( bResort ) 848 aCharAttribList.ResortAttribs(); 849 850 #ifndef SVX_LIGHT 851 if ( pWrongList ) 852 { 853 sal_Bool bSep = ( GetChar( nIndex ) == ' ' ) || IsFeature( nIndex ); 854 pWrongList->TextInserted( nIndex, nNew, bSep ); 855 } 856 #endif // !SVX_LIGHT 857 858 #ifdef EDITDEBUG 859 DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Expand: Start-Liste verdreht" ); 860 #endif 861 } 862 863 void ContentNode::CollapsAttribs( sal_uInt16 nIndex, sal_uInt16 nDeleted, SfxItemPool& rItemPool ) 864 { 865 if ( !nDeleted ) 866 return; 867 868 // Da Features anders behandelt werden als normale Zeichenattribute, 869 // kann sich hier auch die Sortierung der Start-Liste aendern! 870 sal_Bool bResort = sal_False; 871 sal_Bool bDelAttr = sal_False; 872 sal_uInt16 nEndChanges = nIndex+nDeleted; 873 874 sal_uInt16 nAttr = 0; 875 EditCharAttrib* pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); 876 while ( pAttrib ) 877 { 878 bDelAttr = sal_False; 879 if ( pAttrib->GetEnd() >= nIndex ) 880 { 881 // Alles Attribute hinter der Einfuegeposition verschieben... 882 if ( pAttrib->GetStart() >= nEndChanges ) 883 { 884 pAttrib->MoveBackward( nDeleted ); 885 } 886 // 1. Innenliegende Attribute loeschen... 887 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) 888 { 889 // Spezialfall: Attrubt deckt genau den Bereich ab 890 // => als leeres Attribut behalten. 891 if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) 892 pAttrib->GetEnd() = nIndex; // leer 893 else 894 bDelAttr = sal_True; 895 } 896 // 2. Attribut beginnt davor, endet drinnen oder dahinter... 897 else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) 898 { 899 DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); 900 if ( pAttrib->GetEnd() <= nEndChanges ) // endet drinnen 901 pAttrib->GetEnd() = nIndex; 902 else 903 pAttrib->Collaps( nDeleted ); // endet dahinter 904 } 905 // 3. Attribut beginnt drinnen, endet dahinter... 906 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) 907 { 908 // Features duerfen nicht expandieren! 909 if ( pAttrib->IsFeature() ) 910 { 911 pAttrib->MoveBackward( nDeleted ); 912 bResort = sal_True; 913 } 914 else 915 { 916 pAttrib->GetStart() = nEndChanges; 917 pAttrib->MoveBackward( nDeleted ); 918 } 919 } 920 } 921 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); 922 923 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collaps: Attribut verdreht!" ); 924 DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collaps: Attrib groesser als Absatz!" ); 925 if ( bDelAttr /* || pAttrib->IsEmpty() */ ) 926 { 927 bResort = sal_True; 928 aCharAttribList.GetAttribs().Remove( nAttr ); 929 rItemPool.Remove( *pAttrib->GetItem() ); 930 delete pAttrib; 931 nAttr--; 932 } 933 else if ( pAttrib->IsEmpty() ) 934 aCharAttribList.HasEmptyAttribs() = sal_True; 935 936 nAttr++; 937 pAttrib = GetAttrib( aCharAttribList.GetAttribs(), nAttr ); 938 } 939 940 if ( bResort ) 941 aCharAttribList.ResortAttribs(); 942 943 #ifndef SVX_LIGHT 944 if ( pWrongList ) 945 pWrongList->TextDeleted( nIndex, nDeleted ); 946 #endif // !SVX_LIGHT 947 948 #ifdef EDITDEBUG 949 DBG_ASSERT( CheckOrderedList( aCharAttribList.GetAttribs(), sal_True ), "Collaps: Start-Liste verdreht" ); 950 #endif 951 } 952 953 void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, sal_Bool bKeepEndingAttribs ) 954 { 955 DBG_ASSERT( pPrevNode, "kopieren von Attributen auf einen NULL-Pointer ?" ); 956 957 xub_StrLen nCut = pPrevNode->Len(); 958 959 sal_uInt16 nAttr = 0; 960 EditCharAttrib* pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr ); 961 while ( pAttrib ) 962 { 963 if ( pAttrib->GetEnd() < nCut ) 964 { 965 // bleiben unveraendert.... 966 ; 967 } 968 else if ( pAttrib->GetEnd() == nCut ) 969 { 970 // muessen als leeres Attribut kopiert werden. 971 if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) 972 { 973 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); 974 DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" ); 975 aCharAttribList.InsertAttrib( pNewAttrib ); 976 } 977 } 978 else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) 979 { 980 // Wenn ganz vorne gecuttet wird, muss das Attribut erhalten bleiben! 981 // muessen kopiert und geaendert werden 982 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); 983 DBG_ASSERT( pNewAttrib, "MakeCharAttrib fehlgeschlagen!" ); 984 aCharAttribList.InsertAttrib( pNewAttrib ); 985 // stutzen: 986 pAttrib->GetEnd() = nCut; 987 } 988 else 989 { 990 // alle dahinter verschieben in den neuen Node (this) 991 // pPrevNode->GetCharAttribs().RemoveAttrib( pAttrib ); 992 pPrevNode->GetCharAttribs().GetAttribs().Remove( nAttr ); 993 aCharAttribList.InsertAttrib( pAttrib ); 994 DBG_ASSERT( pAttrib->GetStart() >= nCut, "Start < nCut!" ); 995 DBG_ASSERT( pAttrib->GetEnd() >= nCut, "End < nCut!" ); 996 pAttrib->GetStart() = pAttrib->GetStart() - nCut; 997 pAttrib->GetEnd() = pAttrib->GetEnd() - nCut; 998 nAttr--; 999 } 1000 nAttr++; 1001 pAttrib = GetAttrib( pPrevNode->GetCharAttribs().GetAttribs(), nAttr ); 1002 } 1003 } 1004 1005 void ContentNode::AppendAttribs( ContentNode* pNextNode ) 1006 { 1007 DBG_ASSERT( pNextNode, "kopieren von Attributen von einen NULL-Pointer ?" ); 1008 1009 sal_uInt16 nNewStart = Len(); 1010 1011 #ifdef EDITDEBUG 1012 DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute VOR AppendAttribs kaputt" ); 1013 #endif 1014 1015 sal_uInt16 nAttr = 0; 1016 EditCharAttrib* pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr ); 1017 while ( pAttrib ) 1018 { 1019 // alle Attribute verschieben in den aktuellen Node (this) 1020 sal_Bool bMelted = sal_False; 1021 if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) 1022 { 1023 // Evtl koennen Attribute zusammengefasst werden: 1024 sal_uInt16 nTmpAttr = 0; 1025 EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); 1026 while ( !bMelted && pTmpAttrib ) 1027 { 1028 if ( pTmpAttrib->GetEnd() == nNewStart ) 1029 { 1030 if ( ( pTmpAttrib->Which() == pAttrib->Which() ) && 1031 ( *(pTmpAttrib->GetItem()) == *(pAttrib->GetItem() ) ) ) 1032 { 1033 pTmpAttrib->GetEnd() = 1034 pTmpAttrib->GetEnd() + pAttrib->GetLen(); 1035 pNextNode->GetCharAttribs().GetAttribs().Remove( nAttr ); 1036 // Vom Pool abmelden ?! 1037 delete pAttrib; 1038 bMelted = sal_True; 1039 } 1040 } 1041 ++nTmpAttr; 1042 pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); 1043 } 1044 } 1045 1046 if ( !bMelted ) 1047 { 1048 pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; 1049 pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; 1050 aCharAttribList.InsertAttrib( pAttrib ); 1051 ++nAttr; 1052 } 1053 pAttrib = GetAttrib( pNextNode->GetCharAttribs().GetAttribs(), nAttr ); 1054 } 1055 // Fuer die Attribute, die nur ruebergewandert sind: 1056 pNextNode->GetCharAttribs().Clear(); 1057 1058 #ifdef EDITDEBUG 1059 DBG_ASSERT( aCharAttribList.DbgCheckAttribs(), "Attribute NACH AppendAttribs kaputt" ); 1060 #endif 1061 } 1062 1063 void ContentNode::CreateDefFont() 1064 { 1065 // Erst alle Informationen aus dem Style verwenden... 1066 SfxStyleSheet* pS = aContentAttribs.GetStyleSheet(); 1067 if ( pS ) 1068 CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); 1069 1070 // ... dann die harte Absatzformatierung rueberbuegeln... 1071 CreateFont( GetCharAttribs().GetDefFont(), 1072 GetContentAttribs().GetItems(), pS == NULL ); 1073 } 1074 1075 void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) 1076 { 1077 aContentAttribs.SetStyleSheet( pS ); 1078 1079 // Erst alle Informationen aus dem Style verwenden... 1080 GetCharAttribs().GetDefFont() = rFontFromStyle; 1081 // ... dann die harte Absatzformatierung rueberbuegeln... 1082 CreateFont( GetCharAttribs().GetDefFont(), 1083 GetContentAttribs().GetItems(), pS == NULL ); 1084 } 1085 1086 void ContentNode::SetStyleSheet( SfxStyleSheet* pS, sal_Bool bRecalcFont ) 1087 { 1088 aContentAttribs.SetStyleSheet( pS ); 1089 if ( bRecalcFont ) 1090 CreateDefFont(); 1091 } 1092 1093 void ContentNode::DestroyWrongList() 1094 { 1095 #ifndef SVX_LIGHT 1096 delete pWrongList; 1097 #endif 1098 pWrongList = NULL; 1099 } 1100 1101 void ContentNode::CreateWrongList() 1102 { 1103 DBG_ASSERT( !pWrongList, "WrongList existiert schon!" ); 1104 #ifndef SVX_LIGHT 1105 pWrongList = new WrongList; 1106 #endif 1107 } 1108 1109 void ContentNode::SetWrongList( WrongList* p ) 1110 { 1111 DBG_ASSERT( !pWrongList, "WrongList existiert schon!" ); 1112 pWrongList = p; 1113 } 1114 1115 // ------------------------------------------------------------------------- 1116 // class ContentAttribs 1117 // ------------------------------------------------------------------------- 1118 ContentAttribs::ContentAttribs( SfxItemPool& rPool ) : 1119 aAttribSet( rPool, EE_PARA_START, EE_CHAR_END ) 1120 { 1121 pStyle = 0; 1122 } 1123 1124 ContentAttribs::ContentAttribs( const ContentAttribs& rRef ) : 1125 aAttribSet( rRef.aAttribSet ) 1126 { 1127 pStyle = rRef.pStyle; 1128 } 1129 1130 ContentAttribs::~ContentAttribs() 1131 { 1132 } 1133 1134 SvxTabStop ContentAttribs::FindTabStop( long nCurPos, sal_uInt16 nDefTab ) 1135 { 1136 const SvxTabStopItem& rTabs = (const SvxTabStopItem&) GetItem( EE_PARA_TABS ); 1137 for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) 1138 { 1139 const SvxTabStop& rTab = rTabs[i]; 1140 if ( rTab.GetTabPos() > nCurPos ) 1141 return rTab; 1142 } 1143 1144 // DefTab ermitteln... 1145 SvxTabStop aTabStop; 1146 long x = nCurPos / nDefTab + 1; 1147 aTabStop.GetTabPos() = nDefTab * x; 1148 return aTabStop; 1149 } 1150 1151 void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) 1152 { 1153 sal_Bool bStyleChanged = ( pStyle != pS ); 1154 pStyle = pS; 1155 // #104799# Only when other style sheet, not when current style sheet modified 1156 if ( pStyle && bStyleChanged ) 1157 { 1158 // Gezielt die Attribute aus der Absatzformatierung entfernen, die im Style 1159 // spezifiziert sind, damit die Attribute des Styles wirken koennen. 1160 const SfxItemSet& rStyleAttribs = pStyle->GetItemSet(); 1161 for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) 1162 { 1163 // #99635# Don't change bullet on/off 1164 if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SFX_ITEM_ON ) ) 1165 aAttribSet.ClearItem( nWhich ); 1166 } 1167 } 1168 } 1169 1170 const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) 1171 { 1172 // Harte Absatzattribute haben Vorrang! 1173 SfxItemSet* pTakeFrom = &aAttribSet; 1174 if ( pStyle && ( aAttribSet.GetItemState( nWhich, sal_False ) != SFX_ITEM_ON ) ) 1175 pTakeFrom = &pStyle->GetItemSet(); 1176 1177 return pTakeFrom->Get( nWhich ); 1178 } 1179 1180 sal_Bool ContentAttribs::HasItem( sal_uInt16 nWhich ) 1181 { 1182 sal_Bool bHasItem = sal_False; 1183 if ( aAttribSet.GetItemState( nWhich, sal_False ) == SFX_ITEM_ON ) 1184 bHasItem = sal_True; 1185 else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SFX_ITEM_ON ) 1186 bHasItem = sal_True; 1187 1188 return bHasItem; 1189 } 1190 1191 1192 1193 // ---------------------------------------------------------------------- 1194 // class ItemList 1195 // ---------------------------------------------------------------------- 1196 const SfxPoolItem* ItemList::FindAttrib( sal_uInt16 nWhich ) 1197 { 1198 const SfxPoolItem* pItem = First(); 1199 while ( pItem && ( pItem->Which() != nWhich ) ) 1200 pItem = Next(); 1201 1202 return pItem; 1203 } 1204 1205 // ------------------------------------------------------------------------- 1206 // class EditDoc 1207 // ------------------------------------------------------------------------- 1208 EditDoc::EditDoc( SfxItemPool* pPool ) 1209 { 1210 if ( pPool ) 1211 { 1212 pItemPool = pPool; 1213 bOwnerOfPool = sal_False; 1214 } 1215 else 1216 { 1217 pItemPool = new EditEngineItemPool( sal_False ); 1218 bOwnerOfPool = sal_True; 1219 } 1220 1221 nDefTab = DEFTAB; 1222 bIsVertical = sal_False; 1223 bIsFixedCellHeight = sal_False; 1224 1225 // Don't create a empty node, Clear() will be called in EditEngine-CTOR 1226 1227 SetModified( sal_False ); 1228 }; 1229 1230 EditDoc::~EditDoc() 1231 { 1232 ImplDestroyContents(); 1233 if ( bOwnerOfPool ) 1234 SfxItemPool::Free(pItemPool); 1235 } 1236 1237 void EditDoc::ImplDestroyContents() 1238 { 1239 for ( sal_uInt16 nNode = Count(); nNode; ) 1240 RemoveItemsFromPool( GetObject( --nNode ) ); 1241 DeleteAndDestroy( 0, Count() ); 1242 } 1243 1244 void EditDoc::RemoveItemsFromPool( ContentNode* pNode ) 1245 { 1246 for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ ) 1247 { 1248 EditCharAttrib* pAttr = pNode->GetCharAttribs().GetAttribs()[nAttr]; 1249 GetItemPool().Remove( *pAttr->GetItem() ); 1250 } 1251 } 1252 1253 void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, short nScriptType ) 1254 { 1255 Font aPrevFont( rFont ); 1256 rFont.SetAlign( ALIGN_BASELINE ); 1257 rFont.SetTransparent( sal_True ); 1258 1259 sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); 1260 sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); 1261 sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType ); 1262 sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType ); 1263 sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType ); 1264 1265 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SFX_ITEM_ON ) ) 1266 { 1267 const SvxFontItem& rFontItem = (const SvxFontItem&)rSet.Get( nWhich_FontInfo ); 1268 rFont.SetName( rFontItem.GetFamilyName() ); 1269 rFont.SetFamily( rFontItem.GetFamily() ); 1270 rFont.SetPitch( rFontItem.GetPitch() ); 1271 rFont.SetCharSet( rFontItem.GetCharSet() ); 1272 } 1273 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SFX_ITEM_ON ) ) 1274 rFont.SetLanguage( ((const SvxLanguageItem&)rSet.Get( nWhich_Language )).GetLanguage() ); 1275 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SFX_ITEM_ON ) ) 1276 rFont.SetColor( ((const SvxColorItem&)rSet.Get( EE_CHAR_COLOR )).GetValue() ); 1277 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SFX_ITEM_ON ) ) 1278 rFont.SetSize( Size( rFont.GetSize().Width(), ((const SvxFontHeightItem&)rSet.Get( nWhich_FontHeight ) ).GetHeight() ) ); 1279 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SFX_ITEM_ON ) ) 1280 rFont.SetWeight( ((const SvxWeightItem&)rSet.Get( nWhich_Weight )).GetWeight() ); 1281 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SFX_ITEM_ON ) ) 1282 rFont.SetUnderline( ((const SvxUnderlineItem&)rSet.Get( EE_CHAR_UNDERLINE )).GetLineStyle() ); 1283 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SFX_ITEM_ON ) ) 1284 rFont.SetOverline( ((const SvxOverlineItem&)rSet.Get( EE_CHAR_OVERLINE )).GetLineStyle() ); 1285 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SFX_ITEM_ON ) ) 1286 rFont.SetStrikeout( ((const SvxCrossedOutItem&)rSet.Get( EE_CHAR_STRIKEOUT )).GetStrikeout() ); 1287 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SFX_ITEM_ON ) ) 1288 rFont.SetItalic( ((const SvxPostureItem&)rSet.Get( nWhich_Italic )).GetPosture() ); 1289 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SFX_ITEM_ON ) ) 1290 rFont.SetOutline( ((const SvxContourItem&)rSet.Get( EE_CHAR_OUTLINE )).GetValue() ); 1291 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SFX_ITEM_ON ) ) 1292 rFont.SetShadow( ((const SvxShadowedItem&)rSet.Get( EE_CHAR_SHADOW )).GetValue() ); 1293 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SFX_ITEM_ON ) ) 1294 { 1295 const SvxEscapementItem& rEsc = (const SvxEscapementItem&) rSet.Get( EE_CHAR_ESCAPEMENT ); 1296 1297 sal_uInt16 nProp = rEsc.GetProp(); 1298 rFont.SetPropr( (sal_uInt8)nProp ); 1299 1300 short nEsc = rEsc.GetEsc(); 1301 if ( nEsc == DFLT_ESC_AUTO_SUPER ) 1302 nEsc = 100 - nProp; 1303 else if ( nEsc == DFLT_ESC_AUTO_SUB ) 1304 nEsc = sal::static_int_cast< short >( -( 100 - nProp ) ); 1305 rFont.SetEscapement( nEsc ); 1306 } 1307 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SFX_ITEM_ON ) ) 1308 rFont.SetKerning( ((const SvxAutoKernItem&)rSet.Get( EE_CHAR_PAIRKERNING )).GetValue() ); 1309 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SFX_ITEM_ON ) ) 1310 rFont.SetFixKerning( ((const SvxKerningItem&)rSet.Get( EE_CHAR_KERNING )).GetValue() ); 1311 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SFX_ITEM_ON ) ) 1312 rFont.SetWordLineMode( ((const SvxWordLineModeItem&)rSet.Get( EE_CHAR_WLM )).GetValue() ); 1313 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SFX_ITEM_ON ) ) 1314 rFont.SetEmphasisMark( ((const SvxEmphasisMarkItem&)rSet.Get( EE_CHAR_EMPHASISMARK )).GetValue() ); 1315 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SFX_ITEM_ON ) ) 1316 rFont.SetRelief( (FontRelief)((const SvxCharReliefItem&)rSet.Get( EE_CHAR_RELIEF )).GetValue() ); 1317 1318 // Ob ich jetzt den ganzen Font vergleiche, oder vor jeder Aenderung 1319 // pruefe, ob der Wert sich aendert, bleibt sich relativ gleich. 1320 // So ggf ein MakeUniqFont im Font mehr, dafuer bei Aenderung schnellerer 1321 // Abbruch der Abfrage, oder ich musste noch jedesmal ein bChanged pflegen. 1322 if ( rFont == aPrevFont ) 1323 rFont = aPrevFont; // => Gleicher ImpPointer fuer IsSameInstance 1324 } 1325 1326 void EditDoc::CreateDefFont( sal_Bool bUseStyles ) 1327 { 1328 SfxItemSet aTmpSet( GetItemPool(), EE_PARA_START, EE_CHAR_END ); 1329 CreateFont( aDefFont, aTmpSet ); 1330 aDefFont.SetVertical( IsVertical() ); 1331 aDefFont.SetOrientation( IsVertical() ? 2700 : 0 ); 1332 1333 for ( sal_uInt16 nNode = 0; nNode < Count(); nNode++ ) 1334 { 1335 ContentNode* pNode = GetObject( nNode ); 1336 pNode->GetCharAttribs().GetDefFont() = aDefFont; 1337 if ( bUseStyles ) 1338 pNode->CreateDefFont(); 1339 } 1340 } 1341 1342 static const sal_Unicode aCR[] = { 0x0d, 0x00 }; 1343 static const sal_Unicode aLF[] = { 0x0a, 0x00 }; 1344 static const sal_Unicode aCRLF[] = { 0x0d, 0x0a, 0x00 }; 1345 1346 XubString EditDoc::GetSepStr( LineEnd eEnd ) 1347 { 1348 XubString aSep; 1349 if ( eEnd == LINEEND_CR ) 1350 aSep = aCR; 1351 else if ( eEnd == LINEEND_LF ) 1352 aSep = aLF; 1353 else 1354 aSep = aCRLF; 1355 return aSep; 1356 } 1357 1358 XubString EditDoc::GetText( LineEnd eEnd ) const 1359 { 1360 sal_uLong nLen = GetTextLen(); 1361 sal_uInt16 nNodes = Count(); 1362 1363 String aSep = EditDoc::GetSepStr( eEnd ); 1364 sal_uInt16 nSepSize = aSep.Len(); 1365 1366 if ( nSepSize ) 1367 nLen += nNodes * nSepSize; 1368 if ( nLen > 0xFFFb / sizeof(xub_Unicode) ) 1369 { 1370 DBG_ERROR( "Text zu gross fuer String" ); 1371 return XubString(); 1372 } 1373 xub_Unicode* pStr = new xub_Unicode[nLen+1]; 1374 xub_Unicode* pCur = pStr; 1375 sal_uInt16 nLastNode = nNodes-1; 1376 for ( sal_uInt16 nNode = 0; nNode < nNodes; nNode++ ) 1377 { 1378 XubString aTmp( GetParaAsString( GetObject(nNode) ) ); 1379 memcpy( pCur, aTmp.GetBuffer(), aTmp.Len()*sizeof(sal_Unicode) ); 1380 pCur += aTmp.Len(); 1381 if ( nSepSize && ( nNode != nLastNode ) ) 1382 { 1383 memcpy( pCur, aSep.GetBuffer(), nSepSize*sizeof(sal_Unicode ) ); 1384 pCur += nSepSize; 1385 } 1386 } 1387 *pCur = '\0'; 1388 XubString aASCIIText( pStr ); 1389 delete[] pStr; 1390 return aASCIIText; 1391 } 1392 1393 XubString EditDoc::GetParaAsString( sal_uInt16 nNode ) const 1394 { 1395 return GetParaAsString( SaveGetObject( nNode ) ); 1396 } 1397 1398 XubString EditDoc::GetParaAsString( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, sal_Bool bResolveFields ) const 1399 { 1400 if ( nEndPos > pNode->Len() ) 1401 nEndPos = pNode->Len(); 1402 1403 DBG_ASSERT( nStartPos <= nEndPos, "Start und Ende vertauscht?" ); 1404 1405 sal_uInt16 nIndex = nStartPos; 1406 XubString aStr; 1407 EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature( nIndex ); 1408 while ( nIndex < nEndPos ) 1409 { 1410 sal_uInt16 nEnd = nEndPos; 1411 if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) 1412 nEnd = pNextFeature->GetStart(); 1413 else 1414 pNextFeature = 0; // Feature interessiert unten nicht 1415 1416 DBG_ASSERT( nEnd >= nIndex, "Ende vorm Index?" ); 1417 //!! beware of sub string length of -1 which is also defined as STRING_LEN and 1418 //!! thus would result in adding the whole sub string up to the end of the node !! 1419 if (nEnd > nIndex) 1420 aStr += XubString( *pNode, nIndex, nEnd - nIndex ); 1421 1422 if ( pNextFeature ) 1423 { 1424 switch ( pNextFeature->GetItem()->Which() ) 1425 { 1426 case EE_FEATURE_TAB: aStr += '\t'; 1427 break; 1428 case EE_FEATURE_LINEBR: aStr += '\x0A'; 1429 break; 1430 case EE_FEATURE_FIELD: if ( bResolveFields ) 1431 aStr += ((EditCharAttribField*)pNextFeature)->GetFieldValue(); 1432 break; 1433 default: DBG_ERROR( "Was fuer ein Feature ?" ); 1434 } 1435 pNextFeature = pNode->GetCharAttribs().FindFeature( ++nEnd ); 1436 } 1437 nIndex = nEnd; 1438 } 1439 return aStr; 1440 } 1441 1442 sal_uLong EditDoc::GetTextLen() const 1443 { 1444 sal_uLong nLen = 0; 1445 for ( sal_uInt16 nNode = 0; nNode < Count(); nNode++ ) 1446 { 1447 ContentNode* pNode = GetObject( nNode ); 1448 nLen += pNode->Len(); 1449 // Felder k�nnen laenger sein als der Platzhalter im Node. 1450 const CharAttribArray& rAttrs = pNode->GetCharAttribs().GetAttribs(); 1451 for ( sal_uInt16 nAttr = rAttrs.Count(); nAttr; ) 1452 { 1453 EditCharAttrib* pAttr = rAttrs[--nAttr]; 1454 if ( pAttr->Which() == EE_FEATURE_FIELD ) 1455 { 1456 sal_uInt16 nFieldLen = ((EditCharAttribField*)pAttr)->GetFieldValue().Len(); 1457 if ( !nFieldLen ) 1458 nLen--; 1459 else 1460 nLen += nFieldLen-1; 1461 } 1462 } 1463 } 1464 return nLen; 1465 } 1466 1467 EditPaM EditDoc::Clear() 1468 { 1469 ImplDestroyContents(); 1470 1471 ContentNode* pNode = new ContentNode( GetItemPool() ); 1472 Insert( pNode, 0 ); 1473 1474 CreateDefFont( sal_False ); 1475 1476 SetModified( sal_False ); 1477 1478 EditPaM aPaM( pNode, 0 ); 1479 return aPaM; 1480 } 1481 1482 void EditDoc::SetModified( sal_Bool b ) 1483 { 1484 bModified = b; 1485 if ( bModified ) 1486 { 1487 aModifyHdl.Call( NULL ); 1488 } 1489 } 1490 1491 EditPaM EditDoc::RemoveText() 1492 { 1493 // Das alte ItemSetmerken, damit z.B. im Chart Font behalten bleibt 1494 ContentNode* pPrevFirstNode = GetObject(0); 1495 SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet(); 1496 SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() ); 1497 Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() ); 1498 1499 ImplDestroyContents(); 1500 1501 ContentNode* pNode = new ContentNode( GetItemPool() ); 1502 Insert( pNode, 0 ); 1503 1504 pNode->SetStyleSheet( pPrevStyle, sal_False ); 1505 pNode->GetContentAttribs().GetItems().Set( aPrevSet ); 1506 pNode->GetCharAttribs().GetDefFont() = aPrevFont; 1507 1508 SetModified( sal_True ); 1509 1510 EditPaM aPaM( pNode, 0 ); 1511 return aPaM; 1512 } 1513 1514 void EditDoc::InsertText( const EditPaM& rPaM, xub_Unicode c ) 1515 { 1516 DBG_ASSERT( c != 0x0A, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); 1517 DBG_ASSERT( c != 0x0D, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); 1518 DBG_ASSERT( c != '\t', "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); 1519 1520 rPaM.GetNode()->Insert( c, rPaM.GetIndex() ); 1521 rPaM.GetNode()->ExpandAttribs( rPaM.GetIndex(), 1, GetItemPool() ); 1522 1523 SetModified( sal_True ); 1524 } 1525 1526 EditPaM EditDoc::InsertText( EditPaM aPaM, const XubString& rStr ) 1527 { 1528 DBG_ASSERT( rStr.Search( 0x0A ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); 1529 DBG_ASSERT( rStr.Search( 0x0D ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); 1530 DBG_ASSERT( rStr.Search( '\t' ) == STRING_NOTFOUND, "EditDoc::InsertText: Zeilentrenner in Absatz nicht erlaubt!" ); 1531 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertText1" ); 1532 1533 aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() ); 1534 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.Len(), GetItemPool() ); 1535 aPaM.GetIndex() = aPaM.GetIndex() + rStr.Len(); 1536 1537 SetModified( sal_True ); 1538 1539 return aPaM; 1540 } 1541 1542 EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, sal_Bool bKeepEndingAttribs ) 1543 { 1544 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertParaBreak" ); 1545 ContentNode* pCurNode = aPaM.GetNode(); 1546 sal_uInt16 nPos = GetPos( pCurNode ); 1547 XubString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() ); 1548 aPaM.GetNode()->Erase( aPaM.GetIndex() ); 1549 1550 // the paragraph attributes... 1551 ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() ); 1552 1553 // for a new paragraph we like to have the bullet/numbering visible by default 1554 aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, sal_True), EE_PARA_BULLETSTATE ); 1555 1556 // ContenNode-CTOR kopiert auch die Absatzattribute 1557 ContentNode* pNode = new ContentNode( aStr, aContentAttribs ); 1558 1559 // Den Default-Font kopieren 1560 pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont(); 1561 SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet(); 1562 if ( pStyle ) 1563 { 1564 XubString aFollow( pStyle->GetFollow() ); 1565 if ( aFollow.Len() && ( aFollow != pStyle->GetName() ) ) 1566 { 1567 SfxStyleSheetBase* pNext = pStyle->GetPool().Find( aFollow, pStyle->GetFamily() ); 1568 pNode->SetStyleSheet( (SfxStyleSheet*)pNext ); 1569 } 1570 } 1571 1572 // Zeichenattribute muessen ggf. kopiert bzw gestutzt werden: 1573 pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs ); 1574 1575 Insert( pNode, nPos+1 ); 1576 1577 SetModified( sal_True ); 1578 1579 aPaM.SetNode( pNode ); 1580 aPaM.SetIndex( 0 ); 1581 return aPaM; 1582 } 1583 1584 EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ) 1585 { 1586 DBG_ASSERT( aPaM.GetNode(), "Blinder PaM in EditDoc::InsertFeature" ); 1587 1588 aPaM.GetNode()->Insert( CH_FEATURE, aPaM.GetIndex() ); 1589 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() ); 1590 1591 // Fuer das Feature ein Feature-Attribut anlegen... 1592 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 ); 1593 DBG_ASSERT( pAttrib, "Warum kann ich kein Feature anlegen ?" ); 1594 aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib ); 1595 1596 SetModified( sal_True ); 1597 1598 aPaM.GetIndex()++; 1599 return aPaM; 1600 } 1601 1602 EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ) 1603 { 1604 const EditPaM aPaM( pLeft, pLeft->Len() ); 1605 1606 // Erst die Attribute, da sonst nLen nicht stimmt! 1607 pLeft->AppendAttribs( pRight ); 1608 // Dann den Text... 1609 *pLeft += *pRight; 1610 1611 // der rechte verschwindet. 1612 RemoveItemsFromPool( pRight ); 1613 sal_uInt16 nRight = GetPos( pRight ); 1614 Remove( nRight ); 1615 delete pRight; 1616 1617 SetModified( sal_True ); 1618 1619 return aPaM; 1620 } 1621 1622 EditPaM EditDoc::RemoveChars( EditPaM aPaM, sal_uInt16 nChars ) 1623 { 1624 // Evtl. Features entfernen! 1625 aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars ); 1626 aPaM.GetNode()->CollapsAttribs( aPaM.GetIndex(), nChars, GetItemPool() ); 1627 1628 SetModified( sal_True ); 1629 1630 return aPaM; 1631 } 1632 1633 void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem ) 1634 { 1635 DBG_ASSERT( pNode, "Wohin mit dem Attribut?" ); 1636 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" ); 1637 1638 // fuer Optimierung: 1639 // dieses endet am Anfang der Selektion => kann erweitert werden 1640 EditCharAttrib* pEndingAttrib = 0; 1641 // dieses startet am Ende der Selektion => kann erweitert werden 1642 EditCharAttrib* pStartingAttrib = 0; 1643 1644 DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" ); 1645 1646 RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() ); 1647 1648 if ( pStartingAttrib && pEndingAttrib && 1649 ( *(pStartingAttrib->GetItem()) == rPoolItem ) && 1650 ( *(pEndingAttrib->GetItem()) == rPoolItem ) ) 1651 { 1652 // wird ein groesses Attribut. 1653 pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd(); 1654 GetItemPool().Remove( *(pStartingAttrib->GetItem()) ); 1655 pNode->GetCharAttribs().GetAttribs().Remove( pNode->GetCharAttribs().GetAttribs().GetPos( pStartingAttrib ) ); 1656 delete pStartingAttrib; 1657 } 1658 else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) ) 1659 pStartingAttrib->GetStart() = nStart; 1660 else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) ) 1661 pEndingAttrib->GetEnd() = nEnd; 1662 else 1663 InsertAttrib( rPoolItem, pNode, nStart, nEnd ); 1664 1665 if ( pStartingAttrib ) 1666 pNode->GetCharAttribs().ResortAttribs(); 1667 1668 SetModified( sal_True ); 1669 } 1670 1671 sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, sal_uInt16 nWhich ) 1672 { 1673 EditCharAttrib* pStarting; 1674 EditCharAttrib* pEnding; 1675 return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich ); 1676 } 1677 1678 sal_Bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, sal_uInt16 nWhich ) 1679 { 1680 DBG_ASSERT( pNode, "Wohin mit dem Attribut?" ); 1681 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribut zu gross!" ); 1682 1683 // dieses endet am Anfang der Selektion => kann erweitert werden 1684 rpEnding = 0; 1685 // dieses startet am Ende der Selektion => kann erweitert werden 1686 rpStarting = 0; 1687 1688 sal_Bool bChanged = sal_False; 1689 1690 DBG_ASSERT( nStart <= nEnd, "Kleiner Rechenfehler in InsertAttribInSelection" ); 1691 1692 // ueber die Attribute iterieren... 1693 sal_uInt16 nAttr = 0; 1694 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); 1695 while ( pAttr ) 1696 { 1697 sal_Bool bRemoveAttrib = sal_False; 1698 // MT 11.9.97: 1699 // Ich denke dass in dieser Methode generell keine Features geloescht 1700 // werden sollen. 1701 // => Dann koennen die Feature-Abfragen weiter unten entfallen 1702 sal_uInt16 nAttrWhich = pAttr->Which(); 1703 if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) ) 1704 { 1705 // Attribut beginnt in Selection 1706 if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) ) 1707 { 1708 bChanged = sal_True; 1709 if ( pAttr->GetEnd() > nEnd ) 1710 { 1711 pAttr->GetStart() = nEnd; // dann faengt es dahinter an 1712 rpStarting = pAttr; 1713 if ( nWhich ) 1714 break; // es kann kein weiteres Attrib hier liegen 1715 } 1716 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) ) 1717 { 1718 // Feature nur loeschen, wenn genau an der Stelle 1719 bRemoveAttrib = sal_True; 1720 } 1721 } 1722 1723 // Attribut endet in Selection 1724 else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) ) 1725 { 1726 bChanged = sal_True; 1727 if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() ) 1728 { 1729 pAttr->GetEnd() = nStart; // dann hoert es hier auf 1730 rpEnding = pAttr; 1731 } 1732 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) ) 1733 { 1734 // Feature nur loeschen, wenn genau an der Stelle 1735 bRemoveAttrib = sal_True; 1736 } 1737 } 1738 // Attribut ueberlappt die Selektion 1739 else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) ) 1740 { 1741 bChanged = sal_True; 1742 if ( pAttr->GetStart() == nStart ) 1743 { 1744 pAttr->GetStart() = nEnd; 1745 rpStarting = pAttr; 1746 if ( nWhich ) 1747 break; // es kann weitere Attribute geben! 1748 } 1749 else if ( pAttr->GetEnd() == nEnd ) 1750 { 1751 pAttr->GetEnd() = nStart; 1752 rpEnding = pAttr; 1753 if ( nWhich ) 1754 break; // es kann weitere Attribute geben! 1755 } 1756 else // Attribut muss gesplittet werden... 1757 { 1758 sal_uInt16 nOldEnd = pAttr->GetEnd(); 1759 pAttr->GetEnd() = nStart; 1760 rpEnding = pAttr; 1761 InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd ); 1762 if ( nWhich ) 1763 break; // es kann weitere Attribute geben! 1764 } 1765 } 1766 } 1767 if ( bRemoveAttrib ) 1768 { 1769 DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Loeschen und behalten des gleichen Attributs ?" ); 1770 DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" ); 1771 pNode->GetCharAttribs().GetAttribs().Remove(nAttr); 1772 GetItemPool().Remove( *pAttr->GetItem() ); 1773 delete pAttr; 1774 nAttr--; 1775 } 1776 nAttr++; 1777 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); 1778 } 1779 1780 if ( bChanged ) 1781 { 1782 // char attributes need to be sorted by start again 1783 pNode->GetCharAttribs().ResortAttribs(); 1784 1785 SetModified( sal_True ); 1786 } 1787 1788 return bChanged; 1789 } 1790 1791 void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd ) 1792 { 1793 // Diese Methode prueft nicht mehr, ob ein entspr. Attribut 1794 // schon an der Stelle existiert! 1795 1796 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd ); 1797 DBG_ASSERT( pAttrib, "MakeCharAttrib fehlgeschlagen!" ); 1798 pNode->GetCharAttribs().InsertAttrib( pAttrib ); 1799 1800 SetModified( sal_True ); 1801 } 1802 1803 void EditDoc::InsertAttrib( ContentNode* pNode, sal_uInt16 nStart, sal_uInt16 nEnd, const SfxPoolItem& rPoolItem ) 1804 { 1805 if ( nStart != nEnd ) 1806 { 1807 InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem ); 1808 } 1809 else 1810 { 1811 // Pruefen, ob schon ein neues Attribut mit der WhichId an der Stelle: 1812 EditCharAttrib* pAttr = pNode->GetCharAttribs().FindEmptyAttrib( rPoolItem.Which(), nStart ); 1813 if ( pAttr ) 1814 { 1815 // Attribut entfernen.... 1816 pNode->GetCharAttribs().GetAttribs().Remove( 1817 pNode->GetCharAttribs().GetAttribs().GetPos( pAttr ) ); 1818 delete pAttr; // #i120865#, need free it explicitly 1819 } 1820 1821 // pruefen, ob ein 'gleiches' Attribut an der Stelle liegt. 1822 pAttr = pNode->GetCharAttribs().FindAttrib( rPoolItem.Which(), nStart ); 1823 if ( pAttr ) 1824 { 1825 if ( pAttr->IsInside( nStart ) ) // splitten 1826 { 1827 // ??????????????????????????????? 1828 // eigentlich noch pruefen, ob wirklich splittet, oder return ! 1829 // ??????????????????????????????? 1830 sal_uInt16 nOldEnd = pAttr->GetEnd(); 1831 pAttr->GetEnd() = nStart; 1832 pAttr = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd ); 1833 pNode->GetCharAttribs().InsertAttrib( pAttr ); 1834 } 1835 else if ( pAttr->GetEnd() == nStart ) 1836 { 1837 DBG_ASSERT( !pAttr->IsEmpty(), "Doch noch ein leeres Attribut?" ); 1838 // pruefen, ob genau das gleiche Attribut 1839 if ( *(pAttr->GetItem()) == rPoolItem ) 1840 return; 1841 } 1842 } 1843 InsertAttrib( rPoolItem, pNode, nStart, nStart ); 1844 } 1845 1846 SetModified( sal_True ); 1847 } 1848 1849 void EditDoc::FindAttribs( ContentNode* pNode, sal_uInt16 nStartPos, sal_uInt16 nEndPos, SfxItemSet& rCurSet ) 1850 { 1851 DBG_ASSERT( pNode, "Wo soll ich suchen ?" ); 1852 DBG_ASSERT( nStartPos <= nEndPos, "Ungueltiger Bereich!" ); 1853 1854 sal_uInt16 nAttr = 0; 1855 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); 1856 // keine Selection... 1857 if ( nStartPos == nEndPos ) 1858 { 1859 while ( pAttr && ( pAttr->GetStart() <= nEndPos) ) 1860 { 1861 const SfxPoolItem* pItem = 0; 1862 // Attribut liegt dadrueber... 1863 if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) ) 1864 pItem = pAttr->GetItem(); 1865 // Attribut endet hier, ist nicht leer 1866 else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) ) 1867 { 1868 if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) ) 1869 pItem = pAttr->GetItem(); 1870 } 1871 // Attribut endet hier, ist leer 1872 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) ) 1873 { 1874 pItem = pAttr->GetItem(); 1875 } 1876 // Attribut beginnt hier 1877 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) ) 1878 { 1879 if ( nStartPos == 0 ) // Sonderfall 1880 pItem = pAttr->GetItem(); 1881 } 1882 1883 if ( pItem ) 1884 { 1885 sal_uInt16 nWhich = pItem->Which(); 1886 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF ) 1887 { 1888 rCurSet.Put( *pItem ); 1889 } 1890 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON ) 1891 { 1892 const SfxPoolItem& rItem = rCurSet.Get( nWhich ); 1893 if ( rItem != *pItem ) 1894 { 1895 rCurSet.InvalidateItem( nWhich ); 1896 } 1897 } 1898 } 1899 nAttr++; 1900 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); 1901 } 1902 } 1903 else // Selektion 1904 { 1905 while ( pAttr && ( pAttr->GetStart() < nEndPos) ) 1906 { 1907 const SfxPoolItem* pItem = 0; 1908 // Attribut liegt dadrueber... 1909 if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) ) 1910 pItem = pAttr->GetItem(); 1911 // Attribut startet mitten drin... 1912 else if ( pAttr->GetStart() >= nStartPos ) 1913 { 1914 // !!! pItem = pAttr->GetItem(); 1915 // einfach nur pItem reicht nicht, da ich z.B. bei Shadow 1916 // niemals ein ungleiches Item finden wuerde, da ein solche 1917 // seine Anwesenheit durch Abwesenheit repraesentiert! 1918 // if ( ... ) 1919 // Es muesste geprueft werden, on genau das gleiche Attribut 1920 // an der Bruchstelle aufsetzt, was recht aufwendig ist. 1921 // Da ich beim Einfuegen von Attributen aber etwas optimiere 1922 // tritt der Fall nicht so schnell auf... 1923 // Also aus Geschwindigkeitsgruenden: 1924 rCurSet.InvalidateItem( pAttr->GetItem()->Which() ); 1925 1926 } 1927 // Attribut endet mitten drin... 1928 else if ( pAttr->GetEnd() > nStartPos ) 1929 { 1930 // pItem = pAttr->GetItem(); 1931 // s.o. 1932 /*-----------------31.05.95 16:01------------------- 1933 Ist falsch, wenn das gleiche Attribut sofort wieder 1934 eingestellt wird! 1935 => Sollte am besten nicht vorkommen, also gleich beim 1936 Setzen von Attributen richtig machen! 1937 --------------------------------------------------*/ 1938 rCurSet.InvalidateItem( pAttr->GetItem()->Which() ); 1939 } 1940 1941 if ( pItem ) 1942 { 1943 sal_uInt16 nWhich = pItem->Which(); 1944 if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF ) 1945 { 1946 rCurSet.Put( *pItem ); 1947 } 1948 else if ( rCurSet.GetItemState( nWhich ) == SFX_ITEM_ON ) 1949 { 1950 const SfxPoolItem& rItem = rCurSet.Get( nWhich ); 1951 if ( rItem != *pItem ) 1952 { 1953 rCurSet.InvalidateItem( nWhich ); 1954 } 1955 } 1956 } 1957 nAttr++; 1958 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); 1959 } 1960 } 1961 } 1962 1963 1964 // ------------------------------------------------------------------------- 1965 // class EditCharAttribList 1966 // ------------------------------------------------------------------------- 1967 1968 CharAttribList::CharAttribList() 1969 { 1970 DBG_CTOR( EE_CharAttribList, 0 ); 1971 bHasEmptyAttribs = sal_False; 1972 } 1973 1974 CharAttribList::~CharAttribList() 1975 { 1976 DBG_DTOR( EE_CharAttribList, 0 ); 1977 1978 sal_uInt16 nAttr = 0; 1979 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); 1980 while ( pAttr ) 1981 { 1982 delete pAttr; 1983 ++nAttr; 1984 pAttr = GetAttrib( aAttribs, nAttr ); 1985 } 1986 Clear(); 1987 } 1988 1989 void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) 1990 { 1991 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1992 // optimieren: binaere Suche ? ! 1993 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1994 1995 // MT: 26.11.98 1996 // Vielleicht aber auch einfach nur rueckwaerts iterieren: 1997 // Der haeufigste und kritischste Fall: Attribute kommen bereits 1998 // sortiert an (InsertBinTextObject!) 1999 // Hier waere auch binaere Suche nicht optimal. 2000 // => Wuerde einiges bringen! 2001 2002 const sal_uInt16 nCount = Count(); 2003 const sal_uInt16 nStart = pAttrib->GetStart(); // vielleicht besser fuer Comp.Opt. 2004 2005 if ( pAttrib->IsEmpty() ) 2006 bHasEmptyAttribs = sal_True; 2007 2008 sal_Bool bInserted = sal_False; 2009 for ( sal_uInt16 x = 0; x < nCount; x++ ) 2010 { 2011 EditCharAttribPtr pCurAttrib = aAttribs[x]; 2012 if ( pCurAttrib->GetStart() > nStart ) 2013 { 2014 aAttribs.Insert( pAttrib, x ); 2015 bInserted = sal_True; 2016 break; 2017 } 2018 } 2019 if ( !bInserted ) 2020 aAttribs.Insert( pAttrib, nCount ); 2021 } 2022 2023 void CharAttribList::ResortAttribs() 2024 { 2025 if ( Count() ) 2026 { 2027 #if defined __SUNPRO_CC 2028 #pragma disable_warn 2029 #endif 2030 qsort( (void*)aAttribs.GetData(), aAttribs.Count(), sizeof( EditCharAttrib* ), CompareStart ); 2031 #if defined __SUNPRO_CC 2032 #pragma enable_warn 2033 #endif 2034 } 2035 } 2036 2037 void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool ) 2038 { 2039 for ( sal_uInt16 n = 0; n < aAttribs.Count(); n++ ) 2040 { 2041 EditCharAttrib* pAttr = aAttribs.GetObject( n ); 2042 for ( sal_uInt16 nNext = n+1; nNext < aAttribs.Count(); nNext++ ) 2043 { 2044 EditCharAttrib* p = aAttribs.GetObject( nNext ); 2045 if ( !pAttr->IsFeature() && ( p->GetStart() == pAttr->GetEnd() ) && ( p->Which() == pAttr->Which() ) ) 2046 { 2047 if ( *p->GetItem() == *pAttr->GetItem() ) 2048 { 2049 pAttr->GetEnd() = p->GetEnd(); 2050 aAttribs.Remove( nNext ); 2051 rItemPool.Remove( *p->GetItem() ); 2052 delete p; 2053 } 2054 break; // only 1 attr with same which can start here. 2055 } 2056 else if ( p->GetStart() > pAttr->GetEnd() ) 2057 { 2058 break; 2059 } 2060 } 2061 } 2062 } 2063 2064 EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) 2065 { 2066 // Rueckwaerts, falls eins dort endet, das naechste startet. 2067 // => Das startende gilt... 2068 sal_uInt16 nAttr = aAttribs.Count()-1; 2069 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); 2070 while ( pAttr ) 2071 { 2072 if ( ( pAttr->Which() == nWhich ) && pAttr->IsIn(nPos) ) 2073 return pAttr; 2074 pAttr = GetAttrib( aAttribs, --nAttr ); 2075 } 2076 return 0; 2077 } 2078 2079 EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_uInt16 nFromPos ) const 2080 { 2081 DBG_ASSERT( nWhich, "FindNextAttrib: Which?" ); 2082 const sal_uInt16 nAttribs = aAttribs.Count(); 2083 for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ ) 2084 { 2085 EditCharAttrib* pAttr = aAttribs[ nAttr ]; 2086 if ( ( pAttr->GetStart() >= nFromPos ) && ( pAttr->Which() == nWhich ) ) 2087 return pAttr; 2088 } 2089 return 0; 2090 } 2091 2092 sal_Bool CharAttribList::HasAttrib( sal_uInt16 nWhich ) const 2093 { 2094 for ( sal_uInt16 nAttr = aAttribs.Count(); nAttr; ) 2095 { 2096 const EditCharAttrib* pAttr = aAttribs[--nAttr]; 2097 if ( pAttr->Which() == nWhich ) 2098 return sal_True; 2099 } 2100 return sal_False; 2101 } 2102 2103 sal_Bool CharAttribList::HasAttrib( sal_uInt16 nStartPos, sal_uInt16 nEndPos ) const 2104 { 2105 sal_Bool bAttr = sal_False; 2106 for ( sal_uInt16 nAttr = aAttribs.Count(); nAttr && !bAttr; ) 2107 { 2108 const EditCharAttrib* pAttr = aAttribs[--nAttr]; 2109 if ( ( pAttr->GetStart() < nEndPos ) && ( pAttr->GetEnd() > nStartPos ) ) 2110 return bAttr = sal_True; 2111 } 2112 return bAttr; 2113 } 2114 2115 2116 sal_Bool CharAttribList::HasBoundingAttrib( sal_uInt16 nBound ) 2117 { 2118 // Rueckwaerts, falls eins dort endet, das naechste startet. 2119 // => Das startende gilt... 2120 sal_uInt16 nAttr = aAttribs.Count()-1; 2121 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); 2122 while ( pAttr && ( pAttr->GetEnd() >= nBound ) ) 2123 { 2124 if ( ( pAttr->GetStart() == nBound ) || ( pAttr->GetEnd() == nBound ) ) 2125 return sal_True; 2126 pAttr = GetAttrib( aAttribs, --nAttr ); 2127 } 2128 return sal_False; 2129 } 2130 2131 EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_uInt16 nPos ) 2132 { 2133 if ( !bHasEmptyAttribs ) 2134 return 0; 2135 sal_uInt16 nAttr = 0; 2136 EditCharAttrib* pAttr = GetAttrib( aAttribs, nAttr ); 2137 while ( pAttr && ( pAttr->GetStart() <= nPos ) ) 2138 { 2139 if ( ( pAttr->GetStart() == nPos ) && ( pAttr->GetEnd() == nPos ) && ( pAttr->Which() == nWhich ) ) 2140 return pAttr; 2141 nAttr++; 2142 pAttr = GetAttrib( aAttribs, nAttr ); 2143 } 2144 return 0; 2145 } 2146 2147 EditCharAttrib* CharAttribList::FindFeature( sal_uInt16 nPos ) const 2148 { 2149 2150 sal_uInt16 nAttr = 0; 2151 EditCharAttrib* pNextAttrib = GetAttrib( aAttribs, nAttr ); 2152 2153 // erstmal zur gewuenschten Position... 2154 while ( pNextAttrib && ( pNextAttrib->GetStart() < nPos ) ) 2155 { 2156 nAttr++; 2157 pNextAttrib = GetAttrib( aAttribs, nAttr ); 2158 } 2159 2160 // jetzt das Feature suchen... 2161 while ( pNextAttrib && !pNextAttrib->IsFeature() ) 2162 { 2163 nAttr++; 2164 pNextAttrib = GetAttrib( aAttribs, nAttr ); 2165 } 2166 2167 return pNextAttrib; 2168 } 2169 2170 2171 void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool ) 2172 { 2173 for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) 2174 { 2175 EditCharAttrib* pAttr = aAttribs[nAttr]; 2176 if ( pAttr->IsEmpty() ) 2177 { 2178 rItemPool.Remove( *pAttr->GetItem() ); 2179 aAttribs.Remove( nAttr ); 2180 delete pAttr; 2181 nAttr--; 2182 } 2183 } 2184 bHasEmptyAttribs = sal_False; 2185 } 2186 2187 sal_Bool CharAttribList::DbgCheckAttribs() 2188 { 2189 #ifdef DBG_UTIL 2190 sal_Bool bOK = sal_True; 2191 for ( sal_uInt16 nAttr = 0; nAttr < aAttribs.Count(); nAttr++ ) 2192 { 2193 EditCharAttrib* pAttr = aAttribs[nAttr]; 2194 if ( pAttr->GetStart() > pAttr->GetEnd() ) 2195 { 2196 bOK = sal_False; 2197 DBG_ERROR( "Attr verdreht" ); 2198 } 2199 else if ( pAttr->IsFeature() && ( pAttr->GetLen() != 1 ) ) 2200 { 2201 bOK = sal_False; 2202 DBG_ERROR( "Feature, Len != 1" ); 2203 } 2204 } 2205 return bOK; 2206 #else 2207 return sal_True; 2208 #endif 2209 } 2210 2211 2212 2213 SvxFontTable::SvxFontTable() 2214 { 2215 } 2216 2217 SvxFontTable::~SvxFontTable() 2218 { 2219 SvxFontItem* pItem = First(); 2220 while( pItem ) 2221 { 2222 delete pItem; 2223 pItem = Next(); 2224 } 2225 } 2226 2227 sal_uLong SvxFontTable::GetId( const SvxFontItem& rFontItem ) 2228 { 2229 SvxFontItem* pItem = First(); 2230 while ( pItem ) 2231 { 2232 if ( *pItem == rFontItem ) 2233 return GetCurKey(); 2234 pItem = Next(); 2235 } 2236 DBG_WARNING( "Font nicht gefunden: GetId()" ); 2237 return 0; 2238 } 2239 2240 SvxColorList::SvxColorList() 2241 { 2242 } 2243 2244 SvxColorList::~SvxColorList() 2245 { 2246 SvxColorItem* pItem = First(); 2247 while( pItem ) 2248 { 2249 delete pItem; 2250 pItem = Next(); 2251 } 2252 } 2253 2254 sal_uLong SvxColorList::GetId( const SvxColorItem& rColorItem ) 2255 { 2256 SvxColorItem* pItem = First(); 2257 while ( pItem ) 2258 { 2259 if ( *pItem == rColorItem ) 2260 return GetCurPos(); 2261 pItem = Next(); 2262 } 2263 DBG_WARNING( "Color nicht gefunden: GetId()" ); 2264 return 0; 2265 } 2266 2267 EditEngineItemPool::EditEngineItemPool( sal_Bool bPersistenRefCounts ) 2268 : SfxItemPool( String( "EditEngineItemPool", RTL_TEXTENCODING_ASCII_US ), EE_ITEMS_START, EE_ITEMS_END, 2269 aItemInfos, 0, bPersistenRefCounts ) 2270 { 2271 SetVersionMap( 1, 3999, 4015, aV1Map ); 2272 SetVersionMap( 2, 3999, 4019, aV2Map ); 2273 SetVersionMap( 3, 3997, 4020, aV3Map ); 2274 SetVersionMap( 4, 3994, 4022, aV4Map ); 2275 SetVersionMap( 5, 3994, 4037, aV5Map ); 2276 2277 DBG_ASSERT( EE_DLL(), "EditDLL?!" ); 2278 SfxPoolItem** ppDefItems = EE_DLL()->GetGlobalData()->GetDefItems(); 2279 SetDefaults( ppDefItems ); 2280 } 2281 2282 EditEngineItemPool::~EditEngineItemPool() 2283 { 2284 } 2285 2286 SvStream& EditEngineItemPool::Store( SvStream& rStream ) const 2287 { 2288 // Bei einem 3.1-Export muess ein Hack eingebaut werden, da BUG im 2289 // SfxItemSet::Load, aber nicht nachtraeglich in 3.1 fixbar. 2290 2291 // Der eingestellte Range muss nach Store erhalten bleiben, weil dann 2292 // erst die ItemSets gespeichert werden... 2293 2294 long nVersion = rStream.GetVersion(); 2295 sal_Bool b31Format = ( nVersion && ( nVersion <= SOFFICE_FILEFORMAT_31 ) ) 2296 ? sal_True : sal_False; 2297 2298 EditEngineItemPool* pThis = (EditEngineItemPool*)this; 2299 if ( b31Format ) 2300 pThis->SetStoringRange( 3997, 4022 ); 2301 else 2302 pThis->SetStoringRange( EE_ITEMS_START, EE_ITEMS_END ); 2303 2304 return SfxItemPool::Store( rStream ); 2305 } 2306