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_sw.hxx" 26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ 27 28 #include <com/sun/star/embed/ElementModes.hpp> 29 #include <com/sun/star/embed/XStorage.hpp> 30 31 #include <hash_set> 32 #include <unotools/ucbstreamhelper.hxx> 33 #include <tools/solar.h> 34 #include <rtl/tencinfo.h> 35 #include <rtl/random.h> 36 37 #include <sot/storage.hxx> 38 #include <sfx2/docinf.hxx> 39 #include <sfx2/docfile.hxx> 40 #include <sfx2/request.hxx> 41 #include <sfx2/frame.hxx> 42 #include <tools/urlobj.hxx> 43 #include <unotools/tempfile.hxx> 44 #include <svtools/sfxecode.hxx> 45 46 #include <comphelper/docpasswordrequest.hxx> 47 #include <hintids.hxx> 48 49 #include <editeng/tstpitem.hxx> 50 #include <editeng/cscoitem.hxx> 51 #include <svx/svdobj.hxx> 52 #include <svx/svdpage.hxx> 53 #include <editeng/paperinf.hxx> 54 #include <editeng/lrspitem.hxx> // SvxLRSpaceItem 55 #include <editeng/ulspitem.hxx> 56 #include <editeng/langitem.hxx> 57 #include <editeng/opaqitem.hxx> 58 #include <editeng/charhiddenitem.hxx> 59 #include <filter/msfilter/svxmsbas.hxx> 60 #include <svx/unoapi.hxx> 61 #include <svx/svdoole2.hxx> 62 #include <filter/msfilter/msdffimp.hxx> 63 #include <svx/svdoashp.hxx> 64 #include <svx/svxerr.hxx> 65 #include <filter/msfilter/mscodec.hxx> 66 #include <svx/svdmodel.hxx> 67 #include <svx/svdogrp.hxx> 68 #include <svx/xflclit.hxx> 69 70 #include <unotools/fltrcfg.hxx> 71 #include <fmtfld.hxx> 72 #include <fmturl.hxx> 73 #include <fmtinfmt.hxx> 74 #include <IMark.hxx> 75 #include <reffld.hxx> 76 #include <fmthdft.hxx> 77 #include <fmtcntnt.hxx> 78 #include <fmtcnct.hxx> 79 #include <fmtanchr.hxx> 80 #include <fmtpdsc.hxx> 81 #include <ftninfo.hxx> 82 #include <fmtftn.hxx> 83 #include <txtftn.hxx> 84 #include <pam.hxx> // fuer SwPam 85 #include <doc.hxx> 86 #include <ndtxt.hxx> // class SwTxtNode 87 #include <pagedesc.hxx> // class SwPageDesc 88 #include <paratr.hxx> 89 #include <fmtclds.hxx> 90 #include <fmtclbl.hxx> 91 #include <section.hxx> 92 #include <docsh.hxx> 93 #include <docufld.hxx> 94 #include <swfltopt.hxx> 95 #include <viewsh.hxx> 96 #include <shellres.hxx> 97 #include <mdiexp.hxx> // Progress 98 #include <statstr.hrc> // ResId fuer Statusleiste 99 #include <swerror.h> // ERR_WW8_... 100 #include <swunodef.hxx> 101 #include <unodraw.hxx> 102 #include <swtable.hxx> // class SwTableLines, ... 103 // #i18732# 104 #include <fmtfollowtextflow.hxx> 105 #include <fchrfmt.hxx> 106 #include <charfmt.hxx> 107 108 109 #include <com/sun/star/i18n/ForbiddenCharacters.hpp> 110 #include <comphelper/extract.hxx> 111 #include <comphelper/sequenceashashmap.hxx> 112 #include <fltini.hxx> 113 114 #include <algorithm> 115 #include <functional> 116 #include "writerhelper.hxx" 117 #include "writerwordglue.hxx" 118 119 120 #include "ww8par2.hxx" // class WW8RStyle, class WW8AnchorPara 121 122 #include <frmatr.hxx> 123 124 #include <math.h> 125 #include <com/sun/star/beans/XPropertyContainer.hpp> 126 127 #include <com/sun/star/beans/PropertyAttribute.hpp> 128 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> 129 #include <com/sun/star/document/XDocumentProperties.hpp> 130 #include <svl/itemiter.hxx> //SfxItemIter 131 132 #include <stdio.h> 133 134 #ifdef DEBUG 135 #include <iostream> 136 #include <dbgoutsw.hxx> 137 #endif 138 139 #include "WW8Sttbf.hxx" 140 #include "WW8FibData.hxx" 141 #define MM_250 1417 // WW-Default fuer Hor. Seitenraender: 2.5 cm 142 #define MM_200 1134 // WW-Default fuer u.Seitenrand: 2.0 cm 143 144 using namespace ::com::sun::star; 145 using namespace sw::util; 146 using namespace sw::types; 147 using namespace nsHdFtFlags; 148 149 150 SwMSDffManager::SwMSDffManager( SwWW8ImplReader& rRdr ) 151 : SvxMSDffManager(*rRdr.pTableStream, rRdr.GetBaseURL(), rRdr.pWwFib->fcDggInfo, 152 rRdr.pDataStream, 0, 0, COL_WHITE, 12, rRdr.pStrm, 153 rRdr.maTracer.GetTrace()), 154 rReader(rRdr), pFallbackStream(0), pOldEscherBlipCache(0) 155 { 156 SetSvxMSDffSettings( GetSvxMSDffSettings() ); 157 nSvxMSDffOLEConvFlags = SwMSDffManager::GetFilterFlags(); 158 } 159 160 sal_uInt32 SwMSDffManager::GetFilterFlags() 161 { 162 sal_uInt32 nFlags(0); 163 if (const SvtFilterOptions* pOpt = SvtFilterOptions::Get()) 164 { 165 if (pOpt->IsMathType2Math()) 166 nFlags |= OLE_MATHTYPE_2_STARMATH; 167 if (pOpt->IsExcel2Calc()) 168 nFlags |= OLE_EXCEL_2_STARCALC; 169 if (pOpt->IsPowerPoint2Impress()) 170 nFlags |= OLE_POWERPOINT_2_STARIMPRESS; 171 if (pOpt->IsWinWord2Writer()) 172 nFlags |= OLE_WINWORD_2_STARWRITER; 173 } 174 return nFlags; 175 } 176 177 /* 178 * I would like to override the default OLE importing to add a test 179 * and conversion of OCX controls from their native OLE type into our 180 * native nonOLE Form Control Objects. 181 * 182 * cmc 183 */ 184 // #i32596# - consider new parameter <_nCalledByGroup> 185 SdrObject* SwMSDffManager::ImportOLE( long nOLEId, 186 const Graphic& rGrf, 187 const Rectangle& rBoundRect, 188 const Rectangle& rVisArea, 189 const int _nCalledByGroup, 190 sal_Int64 nAspect ) const 191 { 192 // #i32596# - no import of OLE object, if it's inside a group. 193 // NOTE: This can be undone, if grouping of Writer fly frames is possible or 194 // if drawing OLE objects are allowed in Writer. 195 if ( _nCalledByGroup > 0 ) 196 { 197 return 0L; 198 } 199 200 SdrObject* pRet = 0; 201 String sStorageName; 202 SotStorageRef xSrcStg; 203 uno::Reference < embed::XStorage > xDstStg; 204 if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg )) 205 { 206 SvStorageRef xSrc = xSrcStg->OpenSotStorage( sStorageName, 207 STREAM_READWRITE| STREAM_SHARE_DENYALL ); 208 ASSERT(rReader.pFormImpl, "No Form Implementation!"); 209 STAR_REFERENCE( drawing::XShape ) xShape; 210 if ( (!(rReader.bIsHeader || rReader.bIsFooter)) && 211 rReader.pFormImpl->ReadOCXStream(xSrc,&xShape,true)) 212 { 213 pRet = GetSdrObjectFromXShape(xShape); 214 } 215 else 216 { 217 ErrCode nError = ERRCODE_NONE; 218 pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg, 219 rGrf, rBoundRect, rVisArea, pStData, nError, nSvxMSDffOLEConvFlags, nAspect ); 220 } 221 } 222 return pRet; 223 } 224 225 void SwMSDffManager::DisableFallbackStream() 226 { 227 ASSERT(!pFallbackStream || !pOldEscherBlipCache, 228 "if you're recursive, you're broken"); 229 pFallbackStream = pStData2; 230 pOldEscherBlipCache = pEscherBlipCache; 231 pEscherBlipCache = 0; 232 pStData2 = 0; 233 } 234 235 void SwMSDffManager::EnableFallbackStream() 236 { 237 pStData2 = pFallbackStream; 238 pEscherBlipCache = pOldEscherBlipCache; 239 pOldEscherBlipCache = 0; 240 pFallbackStream = 0; 241 } 242 243 sal_uInt16 SwWW8ImplReader::GetToggleAttrFlags() const 244 { 245 return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0; 246 } 247 248 sal_uInt16 SwWW8ImplReader::GetToggleBiDiAttrFlags() const 249 { 250 return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0; 251 } 252 253 void SwWW8ImplReader::SetToggleAttrFlags(sal_uInt16 nFlags) 254 { 255 if (pCtrlStck) 256 pCtrlStck->SetToggleAttrFlags(nFlags); 257 } 258 259 void SwWW8ImplReader::SetToggleBiDiAttrFlags(sal_uInt16 nFlags) 260 { 261 if (pCtrlStck) 262 pCtrlStck->SetToggleBiDiAttrFlags(nFlags); 263 } 264 265 266 SdrObject* SwMSDffManager::ProcessObj(SvStream& rSt, 267 DffObjData& rObjData, 268 void* pData, 269 Rectangle& rTextRect, 270 SdrObject* pObj 271 ) 272 { 273 if( !rTextRect.IsEmpty() ) 274 { 275 SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData; 276 SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec; 277 278 // fill Import Record with data 279 pImpRec->nShapeId = rObjData.nShapeId; 280 pImpRec->eShapeType = rObjData.eShapeType; 281 282 rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt, 283 DFF_msofbtClientAnchor, 284 SEEK_FROM_CURRENT_AND_RESTART ); 285 if( rObjData.bClientAnchor ) 286 ProcessClientAnchor( rSt, 287 maShapeRecords.Current()->nRecLen, 288 pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen ); 289 290 rObjData.bClientData = maShapeRecords.SeekToContent( rSt, 291 DFF_msofbtClientData, 292 SEEK_FROM_CURRENT_AND_RESTART ); 293 if( rObjData.bClientData ) 294 ProcessClientData( rSt, 295 maShapeRecords.Current()->nRecLen, 296 pImpRec->pClientDataBuffer, pImpRec->nClientDataLen ); 297 298 299 // process user (== Winword) defined parameters in 0xF122 record 300 // #i84783# - set special value to determine, if property is provided or not. 301 pImpRec->nLayoutInTableCell = 0xFFFFFFFF; 302 if( maShapeRecords.SeekToContent( rSt, 303 DFF_msofbtUDefProp, 304 SEEK_FROM_CURRENT_AND_RESTART ) 305 && maShapeRecords.Current()->nRecLen ) 306 { 307 sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen; 308 sal_uInt32 nUDData; 309 sal_uInt16 nPID; 310 while( 5 < nBytesLeft ) 311 { 312 rSt >> nPID; 313 if ( rSt.GetError() != 0 ) 314 break; 315 rSt >> nUDData; 316 switch( nPID ) 317 { 318 case 0x038F: pImpRec->nXAlign = nUDData; break; 319 case 0x0390: pImpRec->nXRelTo = nUDData; break; 320 case 0x0391: pImpRec->nYAlign = nUDData; break; 321 case 0x0392: pImpRec->nYRelTo = nUDData; break; 322 case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break; 323 } 324 if ( rSt.GetError() != 0 ) 325 break; 326 pImpRec->bHasUDefProp = sal_True; 327 nBytesLeft -= 6; 328 } 329 } 330 331 // Textrahmen, auch Title oder Outline 332 sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 ); 333 if( nTextId ) 334 { 335 SfxItemSet aSet( pSdrModel->GetItemPool() ); 336 337 //Originally anything that as a mso_sptTextBox was created as a 338 //textbox, this was changed to be created as a simple 339 //rect to keep impress happy. For the rest of us we'd like to turn 340 //it back into a textbox again. 341 sal_Bool bIsSimpleDrawingTextBox = (pImpRec->eShapeType == mso_sptTextBox); 342 if (!bIsSimpleDrawingTextBox) 343 { 344 //Either 345 //a) its a simple text object or 346 //b) its a rectangle with text and square wrapping. 347 bIsSimpleDrawingTextBox = 348 ( 349 (pImpRec->eShapeType == mso_sptTextSimple) || 350 ( 351 (pImpRec->eShapeType == mso_sptRectangle) 352 // && (eWrapMode == mso_wrapSquare) 353 && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() ) 354 ) 355 ); 356 } 357 358 // Distance of Textbox to it's surrounding Autoshape 359 sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L); 360 sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L ); 361 sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L ); 362 sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L ); 363 364 ScaleEmu( nTextLeft ); 365 ScaleEmu( nTextRight ); 366 ScaleEmu( nTextTop ); 367 ScaleEmu( nTextBottom ); 368 369 sal_Int32 nTextRotationAngle=0; 370 bool bVerticalText = false; 371 if ( IsProperty( DFF_Prop_txflTextFlow ) ) 372 { 373 MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue( 374 DFF_Prop_txflTextFlow) & 0xFFFF); 375 switch( eTextFlow ) 376 { 377 case mso_txflBtoT: 378 nTextRotationAngle = 9000; 379 break; 380 case mso_txflVertN: 381 case mso_txflTtoBN: 382 nTextRotationAngle = 27000; 383 break; 384 case mso_txflTtoBA: 385 bVerticalText = true; 386 break; 387 case mso_txflHorzA: 388 bVerticalText = true; 389 nTextRotationAngle = 9000; 390 case mso_txflHorzN: 391 default : 392 break; 393 } 394 } 395 396 if (nTextRotationAngle) 397 { 398 while (nTextRotationAngle > 360000) 399 nTextRotationAngle-=9000; 400 switch (nTextRotationAngle) 401 { 402 case 9000: 403 { 404 long nWidth = rTextRect.GetWidth(); 405 rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight(); 406 rTextRect.Bottom() = rTextRect.Top() + nWidth; 407 408 sal_Int32 nOldTextLeft = nTextLeft; 409 sal_Int32 nOldTextRight = nTextRight; 410 sal_Int32 nOldTextTop = nTextTop; 411 sal_Int32 nOldTextBottom = nTextBottom; 412 413 nTextLeft = nOldTextBottom; 414 nTextRight = nOldTextTop; 415 nTextTop = nOldTextLeft; 416 nTextBottom = nOldTextRight; 417 } 418 break; 419 case 27000: 420 { 421 long nWidth = rTextRect.GetWidth(); 422 rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight(); 423 rTextRect.Bottom() = rTextRect.Top() + nWidth; 424 425 sal_Int32 nOldTextLeft = nTextLeft; 426 sal_Int32 nOldTextRight = nTextRight; 427 sal_Int32 nOldTextTop = nTextTop; 428 sal_Int32 nOldTextBottom = nTextBottom; 429 430 nTextLeft = nOldTextTop; 431 nTextRight = nOldTextBottom; 432 nTextTop = nOldTextRight; 433 nTextBottom = nOldTextLeft; 434 } 435 break; 436 default: 437 break; 438 } 439 } 440 441 if (bIsSimpleDrawingTextBox) 442 { 443 SdrObject::Free( pObj ); 444 pObj = new SdrRectObj(OBJ_TEXT, rTextRect); 445 } 446 447 // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin, 448 // hier rausrechnen 449 Rectangle aNewRect(rTextRect); 450 aNewRect.Bottom() -= nTextTop + nTextBottom; 451 aNewRect.Right() -= nTextLeft + nTextRight; 452 453 // Nur falls es eine einfache Textbox ist, darf der Writer 454 // das Objekt durch einen Rahmen ersetzen, ansonsten 455 if( bIsSimpleDrawingTextBox ) 456 { 457 SvxMSDffShapeInfo aTmpRec( 0, pImpRec->nShapeId ); 458 aTmpRec.bSortByShapeId = sal_True; 459 460 sal_uInt16 nFound; 461 if( GetShapeInfos()->Seek_Entry( &aTmpRec, &nFound ) ) 462 { 463 SvxMSDffShapeInfo& rInfo = *GetShapeInfos()->GetObject(nFound); 464 pImpRec->bReplaceByFly = rInfo.bReplaceByFly; 465 pImpRec->bLastBoxInChain = rInfo.bLastBoxInChain; 466 } 467 } 468 469 if( bIsSimpleDrawingTextBox ) 470 ApplyAttributes( rSt, aSet, rObjData ); 471 472 bool bFitText = false; 473 if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2) 474 { 475 aSet.Put( SdrTextAutoGrowHeightItem( sal_True ) ); 476 aSet.Put( SdrTextMinFrameHeightItem( 477 aNewRect.Bottom() - aNewRect.Top() ) ); 478 aSet.Put( SdrTextMinFrameWidthItem( 479 aNewRect.Right() - aNewRect.Left() ) ); 480 bFitText = true; 481 } 482 else 483 { 484 aSet.Put( SdrTextAutoGrowHeightItem( sal_False ) ); 485 aSet.Put( SdrTextAutoGrowWidthItem( sal_False ) ); 486 } 487 488 switch ( (MSO_WrapMode) 489 GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) ) 490 { 491 case mso_wrapNone : 492 aSet.Put( SdrTextAutoGrowWidthItem( sal_True ) ); 493 pImpRec->bAutoWidth = true; 494 break; 495 case mso_wrapByPoints : 496 aSet.Put( SdrTextContourFrameItem( sal_True ) ); 497 break; 498 default: 499 ; 500 } 501 502 // Abstaende an den Raendern der Textbox setzen 503 aSet.Put( SdrTextLeftDistItem( nTextLeft ) ); 504 aSet.Put( SdrTextRightDistItem( nTextRight ) ); 505 aSet.Put( SdrTextUpperDistItem( nTextTop ) ); 506 aSet.Put( SdrTextLowerDistItem( nTextBottom ) ); 507 pImpRec->nDxTextLeft = nTextLeft; 508 pImpRec->nDyTextTop = nTextTop; 509 pImpRec->nDxTextRight = nTextRight; 510 pImpRec->nDyTextBottom = nTextBottom; 511 512 // --> SJ 2009-03-06 : taking the correct default (which is mso_anchorTop) 513 MSO_Anchor eTextAnchor = 514 (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop ); 515 516 SdrTextVertAdjust eTVA = bVerticalText 517 ? SDRTEXTVERTADJUST_BLOCK 518 : SDRTEXTVERTADJUST_CENTER; 519 SdrTextHorzAdjust eTHA = bVerticalText 520 ? SDRTEXTHORZADJUST_CENTER 521 : SDRTEXTHORZADJUST_BLOCK; 522 523 switch( eTextAnchor ) 524 { 525 case mso_anchorTop: 526 { 527 if ( bVerticalText ) 528 eTHA = SDRTEXTHORZADJUST_RIGHT; 529 else 530 eTVA = SDRTEXTVERTADJUST_TOP; 531 } 532 break; 533 case mso_anchorTopCentered: 534 { 535 if ( bVerticalText ) 536 eTHA = SDRTEXTHORZADJUST_RIGHT; 537 else 538 eTVA = SDRTEXTVERTADJUST_TOP; 539 } 540 break; 541 case mso_anchorMiddle: 542 break; 543 case mso_anchorMiddleCentered: 544 break; 545 case mso_anchorBottom: 546 { 547 if ( bVerticalText ) 548 eTHA = SDRTEXTHORZADJUST_LEFT; 549 else 550 eTVA = SDRTEXTVERTADJUST_BOTTOM; 551 } 552 break; 553 case mso_anchorBottomCentered: 554 { 555 if ( bVerticalText ) 556 eTHA = SDRTEXTHORZADJUST_LEFT; 557 else 558 eTVA = SDRTEXTVERTADJUST_BOTTOM; 559 } 560 break; 561 /* 562 case mso_anchorTopBaseline: 563 case mso_anchorBottomBaseline: 564 case mso_anchorTopCenteredBaseline: 565 case mso_anchorBottomCenteredBaseline: 566 break; 567 */ 568 default: 569 ; 570 } 571 572 aSet.Put( SdrTextVertAdjustItem( eTVA ) ); 573 aSet.Put( SdrTextHorzAdjustItem( eTHA ) ); 574 575 if (pObj != NULL) 576 { 577 pObj->SetMergedItemSet(aSet); 578 pObj->SetModel(pSdrModel); 579 580 if (bVerticalText && dynamic_cast< SdrTextObj* >( pObj ) ) 581 dynamic_cast< SdrTextObj* >( pObj )->SetVerticalWriting(sal_True); 582 583 if ( bIsSimpleDrawingTextBox ) 584 { 585 if ( nTextRotationAngle ) 586 { 587 long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ? 588 rTextRect.GetWidth() : rTextRect.GetHeight(); 589 nMinWH /= 2; 590 Point aPivot(rTextRect.TopLeft()); 591 aPivot.X() += nMinWH; 592 aPivot.Y() += nMinWH; 593 double a = nTextRotationAngle * nPi180; 594 pObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a)); 595 } 596 } 597 598 if ( ( ( rObjData.nSpFlags & SP_FFLIPV ) || mnFix16Angle || nTextRotationAngle ) && dynamic_cast< SdrObjCustomShape* >( pObj ) ) 599 { 600 SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >( pObj ); 601 602 double fExtraTextRotation = 0.0; 603 if ( mnFix16Angle && !( GetPropertyValue( DFF_Prop_FitTextToShape ) & 4 ) ) 604 { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false 605 fExtraTextRotation = -mnFix16Angle; 606 } 607 if ( rObjData.nSpFlags & SP_FFLIPV ) // sj: in ppt the text is flipped, whereas in word the text 608 { // remains unchanged, so we have to take back the flipping here 609 fExtraTextRotation += 18000.0; // because our core will flip text if the shape is flipped. 610 } 611 fExtraTextRotation += nTextRotationAngle; 612 if ( !::basegfx::fTools::equalZero( fExtraTextRotation ) ) 613 { 614 fExtraTextRotation /= 100.0; 615 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); 616 const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) ); 617 com::sun::star::beans::PropertyValue aPropVal; 618 aPropVal.Name = sTextRotateAngle; 619 aPropVal.Value <<= fExtraTextRotation; 620 aGeometryItem.SetPropertyValue( aPropVal ); 621 pCustomShape->SetMergedItem( aGeometryItem ); 622 } 623 } 624 else if ( mnFix16Angle ) 625 { 626 // rotate text with shape ? 627 double a = mnFix16Angle * nPi180; 628 pObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle, 629 sin( a ), cos( a ) ); 630 } 631 } 632 } 633 else if( !pObj ) 634 { 635 // simple rectangular objects are ignored by ImportObj() :-( 636 // this is OK for Draw but not for Calc and Writer 637 // cause here these objects have a default border 638 pObj = new SdrRectObj(rTextRect); 639 pObj->SetModel( pSdrModel ); 640 SfxItemSet aSet( pSdrModel->GetItemPool() ); 641 ApplyAttributes( rSt, aSet, rObjData ); 642 643 const SfxPoolItem* pPoolItem=NULL; 644 SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR, 645 sal_False, &pPoolItem ); 646 if( SFX_ITEM_DEFAULT == eState ) 647 aSet.Put( XFillColorItem( String(), 648 Color( mnDefaultColor ) ) ); 649 pObj->SetMergedItemSet(aSet); 650 } 651 652 //Means that fBehindDocument is set 653 if (GetPropertyValue(DFF_Prop_fPrint) & 0x20) 654 pImpRec->bDrawHell = sal_True; 655 else 656 pImpRec->bDrawHell = sal_False; 657 if (GetPropertyValue(DFF_Prop_fPrint) & 0x02) 658 pImpRec->bHidden = sal_True; 659 pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 ); 660 661 if ( nTextId ) 662 { 663 pImpRec->aTextId.nTxBxS = (sal_uInt16)( nTextId >> 16 ); 664 pImpRec->aTextId.nSequence = (sal_uInt16)nTextId; 665 } 666 667 pImpRec->nDxWrapDistLeft = GetPropertyValue( 668 DFF_Prop_dxWrapDistLeft, 114935L ) / 635L; 669 pImpRec->nDyWrapDistTop = GetPropertyValue( 670 DFF_Prop_dyWrapDistTop, 0 ) / 635L; 671 pImpRec->nDxWrapDistRight = GetPropertyValue( 672 DFF_Prop_dxWrapDistRight, 114935L ) / 635L; 673 pImpRec->nDyWrapDistBottom = GetPropertyValue( 674 DFF_Prop_dyWrapDistBottom, 0 ) / 635L; 675 // 16.16 fraction times total image width or height, as appropriate. 676 677 if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt)) 678 { 679 delete pImpRec->pWrapPolygon; 680 pImpRec->pWrapPolygon = NULL; 681 682 sal_uInt16 nNumElemVert, nNumElemMemVert, nElemSizeVert; 683 rSt >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert; 684 if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4))) 685 { 686 pImpRec->pWrapPolygon = new Polygon(nNumElemVert); 687 for (sal_uInt16 i = 0; i < nNumElemVert; ++i) 688 { 689 sal_Int32 nX, nY; 690 if (nElemSizeVert == 8) 691 rSt >> nX >> nY; 692 else 693 { 694 sal_Int16 nSmallX, nSmallY; 695 rSt >> nSmallX >> nSmallY; 696 nX = nSmallX; 697 nY = nSmallY; 698 } 699 (*(pImpRec->pWrapPolygon))[i].X() = nX; 700 (*(pImpRec->pWrapPolygon))[i].Y() = nY; 701 } 702 } 703 } 704 705 pImpRec->nCropFromTop = GetPropertyValue( 706 DFF_Prop_cropFromTop, 0 ); 707 pImpRec->nCropFromBottom = GetPropertyValue( 708 DFF_Prop_cropFromBottom, 0 ); 709 pImpRec->nCropFromLeft = GetPropertyValue( 710 DFF_Prop_cropFromLeft, 0 ); 711 pImpRec->nCropFromRight = GetPropertyValue( 712 DFF_Prop_cropFromRight, 0 ); 713 714 sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash ); 715 if ( !IsHardAttribute( DFF_Prop_fLine ) && 716 pImpRec->eShapeType == mso_sptPictureFrame ) 717 { 718 nLineFlags &= ~0x08; 719 } 720 pImpRec->eLineStyle = (nLineFlags & 8) 721 ? (MSO_LineStyle)GetPropertyValue( 722 DFF_Prop_lineStyle, 723 mso_lineSimple ) 724 : (MSO_LineStyle)USHRT_MAX; 725 726 pImpRec->nFlags = rObjData.nSpFlags; 727 728 if( pImpRec->nShapeId ) 729 { 730 // Import-Record-Liste ergaenzen 731 pImpRec->pObj = pObj; 732 rImportData.aRecords.Insert( pImpRec ); 733 734 // Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen 735 /*Only store objects which are not deep inside the tree*/ 736 if( ( rObjData.nCalledByGroup == 0 ) 737 || 738 ( (rObjData.nSpFlags & SP_FGROUP) 739 && (rObjData.nCalledByGroup < 2) ) 740 ) 741 StoreShapeOrder( pImpRec->nShapeId, 742 ( ( (sal_uLong)pImpRec->aTextId.nTxBxS ) << 16 ) 743 + pImpRec->aTextId.nSequence, pObj ); 744 } 745 else 746 delete pImpRec; 747 } 748 749 return pObj; 750 } 751 752 /*************************************************************************** 753 # Spezial FastSave - Attribute 754 #**************************************************************************/ 755 756 void SwWW8ImplReader::Read_StyleCode( sal_uInt16, const sal_uInt8* pData, short nLen ) 757 { 758 if (nLen < 0) 759 { 760 bCpxStyle = false; 761 return; 762 } 763 sal_uInt16 nColl = 0; 764 if (pWwFib->GetFIBVersion() <= ww::eWW2) 765 nColl = *pData; 766 else 767 nColl = SVBT16ToShort(pData); 768 if (nColl < nColls) 769 { 770 SetTxtFmtCollAndListLevel( *pPaM, pCollA[nColl] ); 771 bCpxStyle = true; 772 } 773 } 774 775 // Read_Majority ist fuer Majority ( 103 ) und Majority50 ( 108 ) 776 void SwWW8ImplReader::Read_Majority( sal_uInt16, const sal_uInt8* , short ) 777 { 778 } 779 780 //----------------------------------------- 781 // Stack 782 //----------------------------------------- 783 void SwWW8FltControlStack::NewAttr(const SwPosition& rPos, 784 const SfxPoolItem& rAttr) 785 { 786 ASSERT(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put" 787 "fields into the control stack"); 788 ASSERT(RES_FLTR_REDLINE != rAttr.Which(), "probably don't want to put" 789 "redlines into the control stack"); 790 SwFltControlStack::NewAttr(rPos, rAttr); 791 } 792 793 void SwWW8FltControlStack::SetAttr(const SwPosition& rPos, sal_uInt16 nAttrId, 794 sal_Bool bTstEnde, long nHand, sal_Bool ) 795 { 796 //Doing a textbox, and using the control stack only as a temporary 797 //collection point for properties which will are not to be set into 798 //the real document 799 if (rReader.pPlcxMan && rReader.pPlcxMan->GetDoingDrawTextBox()) 800 { 801 sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count()); 802 for (sal_uInt16 i=0; i < nCnt; ++i) 803 { 804 SwFltStackEntry* pEntry = (*this)[i]; 805 if (nAttrId == pEntry->pAttr->Which()) 806 { 807 DeleteAndDestroy(i--); 808 --nCnt; 809 } 810 } 811 } 812 else //Normal case, set the attribute into the document 813 SwFltControlStack::SetAttr(rPos, nAttrId, bTstEnde, nHand); 814 } 815 816 long GetListFirstLineIndent(const SwNumFmt &rFmt) 817 { 818 ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION, 819 "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" ); 820 821 SvxAdjust eAdj = rFmt.GetNumAdjust(); 822 long nReverseListIndented; 823 if (eAdj == SVX_ADJUST_RIGHT) 824 nReverseListIndented = -rFmt.GetCharTextDistance(); 825 else if (eAdj == SVX_ADJUST_CENTER) 826 nReverseListIndented = rFmt.GetFirstLineOffset()/2; 827 else 828 nReverseListIndented = rFmt.GetFirstLineOffset(); 829 return nReverseListIndented; 830 } 831 832 long lcl_GetTrueMargin(const SvxLRSpaceItem &rLR, const SwNumFmt &rFmt, 833 long &rFirstLinePos) 834 { 835 ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION, 836 "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" ); 837 838 const long nBodyIndent = rLR.GetTxtLeft(); 839 const long nFirstLineDiff = rLR.GetTxtFirstLineOfst(); 840 rFirstLinePos = nBodyIndent + nFirstLineDiff; 841 842 const long nPseudoListBodyIndent = rFmt.GetAbsLSpace(); 843 const long nReverseListIndented = GetListFirstLineIndent(rFmt); 844 long nExtraListIndent = nPseudoListBodyIndent + nReverseListIndented; 845 846 return nExtraListIndent > 0 ? nExtraListIndent : 0; 847 } 848 849 void SyncIndentWithList( SvxLRSpaceItem &rLR, 850 const SwNumFmt &rFmt, 851 const bool bFirstLineOfstSet, 852 const bool bLeftIndentSet ) 853 { 854 if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 855 { 856 long nWantedFirstLinePos; 857 long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos); 858 rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent); 859 rLR.SetTxtFirstLineOfst(0); 860 } 861 else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) 862 { 863 if ( !bFirstLineOfstSet && bLeftIndentSet && 864 rFmt.GetFirstLineIndent() != 0 ) 865 { 866 rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() ); 867 } 868 else if ( bFirstLineOfstSet && !bLeftIndentSet && 869 rFmt.GetIndentAt() != 0 ) 870 { 871 rLR.SetTxtLeft( rFmt.GetIndentAt() ); 872 } 873 else if (!bFirstLineOfstSet && !bLeftIndentSet ) 874 { 875 if ( rFmt.GetFirstLineIndent() != 0 ) 876 { 877 rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() ); 878 } 879 if ( rFmt.GetIndentAt() != 0 ) 880 { 881 rLR.SetTxtLeft( rFmt.GetIndentAt() ); 882 } 883 } 884 } 885 } 886 887 const SwNumFmt* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition &rPos, 888 const SwTxtNode &rTxtNode) 889 { 890 const SwNumFmt *pRet = 0; 891 const SfxPoolItem *pItem = GetStackAttr(rPos, RES_FLTR_NUMRULE); 892 if (pItem && rTxtNode.GetNumRule()) 893 { 894 String sName(((SfxStringItem*)pItem)->GetValue()); 895 if (rTxtNode.IsCountedInList()) 896 { 897 const SwNumRule *pRule = pDoc->FindNumRulePtr(sName); 898 sal_uInt8 nLvl = static_cast< sal_uInt8 >(rTxtNode.GetActualListLevel()); 899 pRet = &(pRule->Get(nLvl)); 900 } 901 } 902 return pRet; 903 } 904 905 //Modify here for #119405, by easyfan, 2012-05-24 906 sal_Int32 SwWW8FltControlStack::GetCurrAttrCP() const 907 { 908 return rReader.GetCurrAttrCP(); 909 } 910 bool SwWW8FltControlStack::IsParaEndInCPs(sal_Int32 nStart,sal_Int32 nEnd,bool bSdOD) const 911 { 912 return rReader.IsParaEndInCPs(nStart,nEnd,bSdOD); 913 } 914 //End of modification, by easyfan 915 //Modify for #119405 by chengjh, 2012-08-16 916 //Clear the para end position recorded in reader intermittently for the least impact on loading performance 917 void SwWW8FltControlStack::ClearParaEndPosition() 918 { 919 if ( Count() != 0 ) 920 return; 921 922 rReader.ClearParaEndPosition(); 923 } 924 bool SwWW8FltControlStack::CheckSdOD(sal_Int32 nStart,sal_Int32 nEnd) 925 { 926 return rReader.IsParaEndInCPs(nStart,nEnd); 927 } 928 //End 929 void SwWW8FltControlStack::SetAttrInDoc(const SwPosition& rTmpPos, 930 SwFltStackEntry* pEntry) 931 { 932 switch( pEntry->pAttr->Which() ) 933 { 934 case RES_LR_SPACE: 935 { 936 /* 937 Loop over the affect nodes and 938 a) convert the word style absolute indent to indent relative 939 to any numbering indent active on the nodes 940 b) adjust the writer style tabstops relative to the old 941 paragraph indent to be relative to the new paragraph indent 942 */ 943 using namespace sw::util; 944 SwPaM aRegion(rTmpPos); 945 if (pEntry->MakeRegion(pDoc, aRegion, false)) 946 { 947 SvxLRSpaceItem aNewLR( *(SvxLRSpaceItem*)pEntry->pAttr ); 948 sal_uLong nStart = aRegion.Start()->nNode.GetIndex(); 949 sal_uLong nEnd = aRegion.End()->nNode.GetIndex(); 950 for(; nStart <= nEnd; ++nStart) 951 { 952 SwNode* pNode = pDoc->GetNodes()[ nStart ]; 953 if (!pNode || !pNode->IsTxtNode()) 954 continue; 955 956 SwCntntNode* pNd = (SwCntntNode*)pNode; 957 SvxLRSpaceItem aOldLR = (const SvxLRSpaceItem&)pNd->GetAttr(RES_LR_SPACE); 958 959 SwTxtNode *pTxtNode = (SwTxtNode*)pNode; 960 961 const SwNumFmt *pNum = 0; 962 pNum = GetNumFmtFromStack( *aRegion.GetPoint(), *pTxtNode ); 963 if (!pNum) 964 { 965 pNum = GetNumFmtFromTxtNode(*pTxtNode); 966 } 967 968 if ( pNum ) 969 { 970 const bool bFirstLineIndentSet = 971 ( rReader.maTxtNodesHavingFirstLineOfstSet.end() != 972 rReader.maTxtNodesHavingFirstLineOfstSet.find( pNode ) ); 973 const bool bLeftIndentSet = 974 ( rReader.maTxtNodesHavingLeftIndentSet.end() != 975 rReader.maTxtNodesHavingLeftIndentSet.find( pNode ) ); 976 SyncIndentWithList( aNewLR, *pNum, 977 bFirstLineIndentSet, 978 bLeftIndentSet ); 979 } 980 981 if (aNewLR == aOldLR) 982 continue; 983 984 pNd->SetAttr(aNewLR); 985 986 } 987 } 988 } 989 break; 990 case RES_TXTATR_FIELD: 991 ASSERT(!this, "What is a field doing in the control stack," 992 "probably should have been in the endstack"); 993 break; 994 case RES_TXTATR_INETFMT: 995 { 996 SwPaM aRegion(rTmpPos); 997 if (pEntry->MakeRegion(pDoc, aRegion, false)) 998 { 999 SwFrmFmt *pFrm; 1000 //If we have just one single inline graphic then 1001 //don't insert a field for the single frame, set 1002 //the frames hyperlink field attribute directly. 1003 if (0 != (pFrm = rReader.ContainsSingleInlineGraphic(aRegion))) 1004 { 1005 const SwFmtINetFmt *pAttr = (const SwFmtINetFmt *) 1006 pEntry->pAttr; 1007 SwFmtURL aURL; 1008 aURL.SetURL(pAttr->GetValue(), false); 1009 aURL.SetTargetFrameName(pAttr->GetTargetFrame()); 1010 pFrm->SetFmtAttr(aURL); 1011 } 1012 else 1013 { 1014 pDoc->InsertPoolItem(aRegion, *pEntry->pAttr, 0); 1015 } 1016 } 1017 } 1018 break; 1019 default: 1020 SwFltControlStack::SetAttrInDoc(rTmpPos, pEntry); 1021 break; 1022 } 1023 } 1024 1025 const SfxPoolItem* SwWW8FltControlStack::GetFmtAttr(const SwPosition& rPos, 1026 sal_uInt16 nWhich) 1027 { 1028 const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich); 1029 if (!pItem) 1030 { 1031 SwCntntNode const*const pNd = rPos.nNode.GetNode().GetCntntNode(); 1032 if (!pNd) 1033 pItem = &pDoc->GetAttrPool().GetDefaultItem(nWhich); 1034 else 1035 { 1036 /* 1037 If we're hunting for the indent on a paragraph and need to use the 1038 parent style indent, then return the indent in msword format, and 1039 not writer format, because that's the style that the filter works 1040 in (naturally) 1041 */ 1042 if (nWhich == RES_LR_SPACE) 1043 { 1044 SfxItemState eState = SFX_ITEM_DEFAULT; 1045 if (const SfxItemSet *pSet = pNd->GetpSwAttrSet()) 1046 eState = pSet->GetItemState(RES_LR_SPACE, false); 1047 if (eState != SFX_ITEM_SET && rReader.pCollA != NULL) 1048 pItem = &(rReader.pCollA[rReader.nAktColl].maWordLR); 1049 } 1050 1051 if (!pItem) 1052 pItem = &pNd->GetAttr(nWhich); 1053 } 1054 } 1055 return pItem; 1056 } 1057 1058 const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos, 1059 sal_uInt16 nWhich) 1060 { 1061 SwNodeIndex aNode( rPos.nNode, -1 ); 1062 sal_uInt16 nIdx = rPos.nContent.GetIndex(); 1063 1064 sal_uInt16 nSize = static_cast< sal_uInt16 >(Count()); 1065 while (nSize) 1066 { 1067 const SwFltStackEntry* pEntry = (*this)[ --nSize ]; 1068 if (pEntry->pAttr->Which() == nWhich) 1069 { 1070 if ( (pEntry->bLocked) || ( 1071 (pEntry->nMkNode <= aNode) && (pEntry->nPtNode >= aNode) && 1072 (pEntry->nMkCntnt <= nIdx) && (pEntry->nPtCntnt >= nIdx) ) ) 1073 { 1074 return (const SfxPoolItem*)pEntry->pAttr; 1075 } 1076 } 1077 } 1078 return 0; 1079 } 1080 1081 bool SwWW8FltRefStack::IsFtnEdnBkmField(const SwFmtFld& rFmtFld, sal_uInt16& rBkmNo) 1082 { 1083 const SwField* pFld = rFmtFld.GetFld(); 1084 sal_uInt16 nSubType; 1085 if(pFld && (RES_GETREFFLD == pFld->Which()) 1086 && ((REF_FOOTNOTE == (nSubType = pFld->GetSubType())) || (REF_ENDNOTE == nSubType)) 1087 && ((SwGetRefField*)pFld)->GetSetRefName().Len()) 1088 { 1089 const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1090 IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( 1091 ((SwGetRefField*)pFld)->GetSetRefName()); 1092 if(ppBkmk != pMarkAccess->getMarksEnd()) 1093 { 1094 // find Sequence No of corresponding Foot-/Endnote 1095 rBkmNo = ppBkmk - pMarkAccess->getMarksBegin(); 1096 return true; 1097 } 1098 } 1099 return false; 1100 } 1101 1102 void SwWW8FltRefStack::SetAttrInDoc(const SwPosition& rTmpPos, 1103 SwFltStackEntry* pEntry) 1104 { 1105 switch( pEntry->pAttr->Which() ) 1106 { 1107 /* 1108 Look up these in our lists of bookmarks that were changed to 1109 variables, and replace the ref field with a var field, otherwise 1110 do normal (?) strange stuff 1111 */ 1112 case RES_TXTATR_FIELD: 1113 { 1114 SwNodeIndex aIdx(pEntry->nMkNode, 1); 1115 SwPaM aPaM(aIdx, pEntry->nMkCntnt); 1116 1117 SwFmtFld& rFmtFld = *(SwFmtFld*)pEntry->pAttr; 1118 SwField* pFld = rFmtFld.GetFld(); 1119 1120 if (!RefToVar(pFld,pEntry)) 1121 { 1122 sal_uInt16 nBkmNo; 1123 if( IsFtnEdnBkmField(rFmtFld, nBkmNo) ) 1124 { 1125 ::sw::mark::IMark const * const pMark = (pDoc->getIDocumentMarkAccess()->getMarksBegin() + nBkmNo)->get(); 1126 1127 const SwPosition& rBkMrkPos = pMark->GetMarkPos(); 1128 1129 SwTxtNode* pTxt = rBkMrkPos.nNode.GetNode().GetTxtNode(); 1130 if( pTxt && rBkMrkPos.nContent.GetIndex() ) 1131 { 1132 SwTxtAttr* const pFtn = pTxt->GetTxtAttrForCharAt( 1133 rBkMrkPos.nContent.GetIndex()-1, RES_TXTATR_FTN ); 1134 if( pFtn ) 1135 { 1136 sal_uInt16 nRefNo = ((SwTxtFtn*)pFtn)->GetSeqRefNo(); 1137 1138 ((SwGetRefField*)pFld)->SetSeqNo( nRefNo ); 1139 1140 if( pFtn->GetFtn().IsEndNote() ) 1141 ((SwGetRefField*)pFld)->SetSubType(REF_ENDNOTE); 1142 } 1143 } 1144 } 1145 } 1146 1147 pDoc->InsertPoolItem(aPaM, *pEntry->pAttr, 0); 1148 MoveAttrs(*aPaM.GetPoint()); 1149 } 1150 break; 1151 case RES_FLTR_TOX: 1152 SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry); 1153 break; 1154 default: 1155 case RES_FLTR_BOOKMARK: 1156 ASSERT(!this, "EndStck used with non field, not what we want"); 1157 SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry); 1158 break; 1159 } 1160 } 1161 1162 /* 1163 For styles we will do our tabstop arithmetic in word style and adjust them to 1164 writer style after all the styles have been finished and the dust settles as 1165 to what affects what. 1166 1167 For explicit attributes we turn the adjusted writer tabstops back into 0 based 1168 word indexes and we'll turn them back into writer indexes when setting them 1169 into the document. If explicit left indent exist which affects them, then this 1170 is handled when the explict left indent is set into the document 1171 */ 1172 void SwWW8ImplReader::Read_Tab(sal_uInt16 , const sal_uInt8* pData, short nLen) 1173 { 1174 if (nLen < 0) 1175 { 1176 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP); 1177 return; 1178 } 1179 1180 short i; 1181 const sal_uInt8* pDel = pData + 1; // Del - Array 1182 sal_uInt8 nDel = pData[0]; 1183 const sal_uInt8* pIns = pData + 2*nDel + 2; // Ins - Array 1184 sal_uInt8 nIns = pData[nDel*2+1]; 1185 WW8_TBD* pTyp = (WW8_TBD*)(pData + 2*nDel + 2*nIns + 2);// Typ - Array 1186 1187 SvxTabStopItem aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP); 1188 1189 const SwTxtFmtColl* pSty = 0; 1190 sal_uInt16 nTabBase; 1191 if (pAktColl) // StyleDef 1192 { 1193 nTabBase = pCollA[nAktColl].nBase; 1194 if (nTabBase < nColls) // Based On 1195 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt; 1196 } 1197 else 1198 { // Text 1199 nTabBase = nAktColl; 1200 pSty = (const SwTxtFmtColl*)pCollA[nAktColl].pFmt; 1201 } 1202 1203 bool bFound = false; 1204 ::std::hash_set<size_t> aLoopWatch; 1205 while (pSty && !bFound) 1206 { 1207 const SfxPoolItem* pTabs; 1208 bFound = pSty->GetAttrSet().GetItemState(RES_PARATR_TABSTOP, false, 1209 &pTabs) == SFX_ITEM_SET; 1210 if( bFound ) 1211 aAttr = *((const SvxTabStopItem*)pTabs); 1212 else 1213 { 1214 1215 sal_uInt16 nOldTabBase = nTabBase; 1216 // If based on another 1217 if (nTabBase < nColls) 1218 nTabBase = pCollA[nTabBase].nBase; 1219 1220 if ( 1221 nTabBase < nColls && 1222 nOldTabBase != nTabBase && 1223 nTabBase != ww::stiNil 1224 ) 1225 { 1226 // #i61789: Stop searching when next style is the same as the 1227 // current one (prevent loop) 1228 aLoopWatch.insert(reinterpret_cast<size_t>(pSty)); 1229 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt; 1230 1231 if (aLoopWatch.find(reinterpret_cast<size_t>(pSty)) != 1232 aLoopWatch.end()) 1233 pSty = 0; 1234 } 1235 else 1236 pSty = 0; // gib die Suche auf 1237 } 1238 } 1239 1240 SvxTabStop aTabStop; 1241 for (i=0; i < nDel; ++i) 1242 { 1243 sal_uInt16 nPos = aAttr.GetPos(SVBT16ToShort(pDel + i*2)); 1244 if( nPos != SVX_TAB_NOTFOUND ) 1245 aAttr.Remove( nPos, 1 ); 1246 } 1247 1248 for (i=0; i < nIns; ++i) 1249 { 1250 short nPos = SVBT16ToShort(pIns + i*2); 1251 aTabStop.GetTabPos() = nPos; 1252 switch( SVBT8ToByte( pTyp[i].aBits1 ) & 0x7 ) // pTyp[i].jc 1253 { 1254 case 0: 1255 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT; 1256 break; 1257 case 1: 1258 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER; 1259 break; 1260 case 2: 1261 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT; 1262 break; 1263 case 3: 1264 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL; 1265 break; 1266 case 4: 1267 continue; // ignoriere Bar 1268 } 1269 1270 switch( SVBT8ToByte( pTyp[i].aBits1 ) >> 3 & 0x7 ) 1271 { 1272 case 0: 1273 aTabStop.GetFill() = ' '; 1274 break; 1275 case 1: 1276 aTabStop.GetFill() = '.'; 1277 break; 1278 case 2: 1279 aTabStop.GetFill() = '-'; 1280 break; 1281 case 3: 1282 case 4: 1283 aTabStop.GetFill() = '_'; 1284 break; 1285 } 1286 1287 sal_uInt16 nPos2 = aAttr.GetPos( nPos ); 1288 if (nPos2 != SVX_TAB_NOTFOUND) 1289 aAttr.Remove(nPos2, 1); // sonst weigert sich das Insert() 1290 aAttr.Insert(aTabStop); 1291 } 1292 1293 if (nIns || nDel) 1294 NewAttr(aAttr); 1295 else 1296 { 1297 //Here we have a tab definition which inserts no extra tabs, or deletes 1298 //no existing tabs. An older version of writer is probably the creater 1299 //of the document :-( . So if we are importing a style we can just 1300 //ignore it. But if we are importing into text we cannot as during 1301 //text SwWW8ImplReader::Read_Tab is called at the begin and end of 1302 //the range the attrib affects, and ignoring it would upset the 1303 //balance 1304 if (!pAktColl) //not importing into a style 1305 { 1306 using namespace sw::util; 1307 SvxTabStopItem aOrig = pSty ? 1308 ItemGet<SvxTabStopItem>(*pSty, RES_PARATR_TABSTOP) : 1309 DefaultItemGet<SvxTabStopItem>(rDoc, RES_PARATR_TABSTOP); 1310 NewAttr(aOrig); 1311 } 1312 } 1313 } 1314 1315 //----------------------------------------- 1316 // DOP 1317 //----------------------------------------- 1318 1319 void SwWW8ImplReader::ImportDop() 1320 { 1321 maTracer.EnterEnvironment(sw::log::eDocumentProperties); 1322 // correct the LastPrinted date in DocumentInfo 1323 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 1324 mpDocShell->GetModel(), uno::UNO_QUERY_THROW); 1325 uno::Reference<document::XDocumentProperties> xDocuProps( 1326 xDPS->getDocumentProperties()); 1327 DBG_ASSERT(xDocuProps.is(), "DocumentProperties is null"); 1328 if (xDocuProps.is()) 1329 { 1330 DateTime aLastPrinted( 1331 sw::ms::DTTM2DateTime(pWDop->dttmLastPrint)); 1332 ::util::DateTime uDT(aLastPrinted.Get100Sec(), 1333 aLastPrinted.GetSec(), aLastPrinted.GetMin(), 1334 aLastPrinted.GetHour(), aLastPrinted.GetDay(), 1335 aLastPrinted.GetMonth(), aLastPrinted.GetYear()); 1336 xDocuProps->setPrintDate(uDT); 1337 } 1338 1339 // 1340 // COMPATIBILITY FLAGS START 1341 // 1342 1343 // #i78951# - remember the unknown compatability options 1344 // so as to export them out 1345 rDoc.Setn32DummyCompatabilityOptions1( pWDop->GetCompatabilityOptions()); 1346 rDoc.Setn32DummyCompatabilityOptions2( pWDop->GetCompatabilityOptions2()); 1347 1348 // Abstand zwischen zwei Absaetzen ist die SUMME von unterem 1349 // Abst. des ersten und oberem Abst. des zweiten 1350 rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX, pWDop->fDontUseHTMLAutoSpacing); 1351 rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true ); 1352 maTracer.Log(sw::log::eDontUseHTMLAutoSpacing); 1353 // move tabs on alignment 1354 rDoc.set(IDocumentSettingAccess::TAB_COMPAT, true); 1355 // #i24363# tab stops relative to indent 1356 rDoc.set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, false); 1357 maTracer.Log(sw::log::eTabStopDistance); 1358 // #i18732# - adjust default of option 'FollowTextFlow' 1359 rDoc.SetDefault( SwFmtFollowTextFlow( sal_False ) ); 1360 1361 // Import Default-Tabs 1362 long nDefTabSiz = pWDop->dxaTab; 1363 if( nDefTabSiz < 56 ) 1364 nDefTabSiz = 709; 1365 1366 // wir wollen genau einen DefaultTab 1367 SvxTabStopItem aNewTab( 1, sal_uInt16(nDefTabSiz), SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP ); 1368 ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT; 1369 1370 rDoc.GetAttrPool().SetPoolDefaultItem( aNewTab ); 1371 1372 if (!pWDop->fUsePrinterMetrics) 1373 maTracer.Log(sw::log::ePrinterMetrics); 1374 1375 if (!pWDop->fNoLeading) 1376 maTracer.Log(sw::log::eExtraLeading); 1377 1378 rDoc.set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, !pWDop->fUsePrinterMetrics); 1379 rDoc.set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true); 1380 rDoc.set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true ); 1381 rDoc.set(IDocumentSettingAccess::ADD_EXT_LEADING, !pWDop->fNoLeading); 1382 1383 rDoc.set(IDocumentSettingAccess::OLD_NUMBERING, false); 1384 1385 // #i47448# 1386 rDoc.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false); 1387 1388 // #i49277# 1389 rDoc.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i56856# 1390 // #i53199# 1391 rDoc.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false); 1392 1393 rDoc.set(IDocumentSettingAccess::OLD_LINE_SPACING, false); 1394 1395 // #i25901#- set new compatibility option 'Add paragraph and table spacing at bottom of table cells' 1396 rDoc.set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true); 1397 1398 // #i11860# - set new compatibility option 'Use former object positioning' to <sal_False> 1399 rDoc.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false); 1400 1401 // #i27767# - set new compatibility option 'Conder Wrapping mode when positioning object' to <sal_True> 1402 rDoc.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true); 1403 1404 // #i13832#, #i24135# 1405 rDoc.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false); 1406 1407 rDoc.set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); 1408 1409 // #i3952# 1410 rDoc.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true); 1411 1412 // 1413 // COMPATIBILITY FLAGS END 1414 // 1415 1416 if (!pWDop->fNoLeading) 1417 maTracer.Log(sw::log::eExtraLeading); 1418 1419 //import magic doptypography information, if its there 1420 if (pWwFib->nFib > 105) 1421 ImportDopTypography(pWDop->doptypography); 1422 1423 // disable form design mode to be able to use imported controls directly 1424 // #i31239# always disable form design mode, not only in protected docs 1425 { 1426 using namespace com::sun::star; 1427 1428 uno::Reference<lang::XComponent> xModelComp(mpDocShell->GetModel(), 1429 uno::UNO_QUERY); 1430 uno::Reference<beans::XPropertySet> xDocProps(xModelComp, 1431 uno::UNO_QUERY); 1432 if (xDocProps.is()) 1433 { 1434 uno::Reference<beans::XPropertySetInfo> xInfo = 1435 xDocProps->getPropertySetInfo(); 1436 sal_Bool bValue = false; 1437 if (xInfo.is()) 1438 { 1439 if (xInfo->hasPropertyByName(C2U("ApplyFormDesignMode"))) 1440 { 1441 xDocProps->setPropertyValue(C2U("ApplyFormDesignMode"), 1442 cppu::bool2any(bValue)); 1443 } 1444 } 1445 } 1446 } 1447 1448 mpDocShell->SetModifyPasswordHash(pWDop->lKeyProtDoc); 1449 1450 const SvtFilterOptions* pOpt = SvtFilterOptions::Get(); 1451 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields()); 1452 if (bUseEnhFields) { 1453 rDoc.set(IDocumentSettingAccess::PROTECT_FORM, pWDop->fProtEnabled ); 1454 } 1455 1456 maTracer.LeaveEnvironment(sw::log::eDocumentProperties); 1457 } 1458 1459 void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography &rTypo) 1460 { 1461 using namespace com::sun::star; 1462 switch (rTypo.iLevelOfKinsoku) 1463 { 1464 case 2: //custom 1465 { 1466 i18n::ForbiddenCharacters aForbidden(rTypo.rgxchFPunct, 1467 rTypo.rgxchLPunct); 1468 rDoc.setForbiddenCharacters(rTypo.GetConvertedLang(), 1469 aForbidden); 1470 //Obviously cannot set the standard level 1 for japanese, so 1471 //bail out now while we can. 1472 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE) 1473 return; 1474 } 1475 break; 1476 default: 1477 break; 1478 } 1479 1480 /* 1481 This MS hack means that level 2 of japanese is not in operation, so we put 1482 in what we know are the MS defaults, there is a complementary reverse 1483 hack in the writer. Its our default as well, but we can set it anyway 1484 as a flag for later. 1485 */ 1486 if (!rTypo.reserved2) 1487 { 1488 i18n::ForbiddenCharacters aForbidden(rTypo.GetJapanNotBeginLevel1(), 1489 rTypo.GetJapanNotEndLevel1()); 1490 rDoc.setForbiddenCharacters(LANGUAGE_JAPANESE,aForbidden); 1491 } 1492 1493 rDoc.set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION, rTypo.fKerningPunct); 1494 rDoc.setCharacterCompressionType(static_cast<SwCharCompressType>(rTypo.iJustification)); 1495 } 1496 1497 //----------------------------------------- 1498 // Fuss- und Endnoten 1499 1500 //----------------------------------------- 1501 1502 WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader* pRdr ,WW8_CP nStartCp) : 1503 maTmpPos(*pRdr->pPaM->GetPoint()), 1504 mpOldStck(pRdr->pCtrlStck), 1505 mpOldAnchorStck(pRdr->pAnchorStck), 1506 mpOldRedlines(pRdr->mpRedlineStack), 1507 mpOldPlcxMan(pRdr->pPlcxMan), 1508 mpWFlyPara(pRdr->pWFlyPara), 1509 mpSFlyPara(pRdr->pSFlyPara), 1510 mpPreviousNumPaM(pRdr->pPreviousNumPaM), 1511 mpPrevNumRule(pRdr->pPrevNumRule), 1512 mpTableDesc(pRdr->pTableDesc), 1513 mnInTable(pRdr->nInTable), 1514 mnAktColl(pRdr->nAktColl), 1515 mcSymbol(pRdr->cSymbol), 1516 mbIgnoreText(pRdr->bIgnoreText), 1517 mbSymbol(pRdr->bSymbol), 1518 mbHdFtFtnEdn(pRdr->bHdFtFtnEdn), 1519 mbTxbxFlySection(pRdr->bTxbxFlySection), 1520 mbAnl(pRdr->bAnl), 1521 mbInHyperlink(pRdr->bInHyperlink), 1522 mbPgSecBreak(pRdr->bPgSecBreak), 1523 mbWasParaEnd(pRdr->bWasParaEnd), 1524 mbHasBorder(pRdr->bHasBorder), 1525 mbFirstPara(pRdr->bFirstPara) 1526 { 1527 pRdr->bSymbol = false; 1528 pRdr->bHdFtFtnEdn = true; 1529 pRdr->bTxbxFlySection = pRdr->bAnl = pRdr->bPgSecBreak = pRdr->bWasParaEnd 1530 = pRdr->bHasBorder = false; 1531 pRdr->bFirstPara = true; 1532 pRdr->nInTable = 0; 1533 pRdr->pWFlyPara = 0; 1534 pRdr->pSFlyPara = 0; 1535 pRdr->pPreviousNumPaM = 0; 1536 pRdr->pPrevNumRule = 0; 1537 pRdr->pTableDesc = 0; 1538 pRdr->nAktColl = 0; 1539 1540 1541 pRdr->pCtrlStck = new SwWW8FltControlStack(&pRdr->rDoc, pRdr->nFieldFlags, 1542 *pRdr); 1543 1544 pRdr->mpRedlineStack = new sw::util::RedlineStack(pRdr->rDoc); 1545 1546 pRdr->pAnchorStck = new SwWW8FltAnchorStack(&pRdr->rDoc, pRdr->nFieldFlags); 1547 1548 // rette die Attributverwaltung: dies ist noetig, da der neu anzulegende 1549 // PLCFx Manager natuerlich auf die gleichen FKPs zugreift, wie der alte 1550 // und deren Start-End-Positionen veraendert... 1551 if (pRdr->pPlcxMan) 1552 pRdr->pPlcxMan->SaveAllPLCFx(maPLCFxSave); 1553 1554 if (nStartCp != -1) 1555 { 1556 pRdr->pPlcxMan = new WW8PLCFMan(pRdr->pSBase, 1557 mpOldPlcxMan->GetManType(), nStartCp); 1558 } 1559 1560 maOldApos.push_back(false); 1561 maOldApos.swap(pRdr->maApos); 1562 maOldFieldStack.swap(pRdr->maFieldStack); 1563 } 1564 1565 void WW8ReaderSave::Restore( SwWW8ImplReader* pRdr ) 1566 { 1567 pRdr->pWFlyPara = mpWFlyPara; 1568 pRdr->pSFlyPara = mpSFlyPara; 1569 pRdr->pPreviousNumPaM = mpPreviousNumPaM; 1570 pRdr->pPrevNumRule = mpPrevNumRule; 1571 pRdr->pTableDesc = mpTableDesc; 1572 pRdr->cSymbol = mcSymbol; 1573 pRdr->bSymbol = mbSymbol; 1574 pRdr->bIgnoreText = mbIgnoreText; 1575 pRdr->bHdFtFtnEdn = mbHdFtFtnEdn; 1576 pRdr->bTxbxFlySection = mbTxbxFlySection; 1577 pRdr->nInTable = mnInTable; 1578 pRdr->bAnl = mbAnl; 1579 pRdr->bInHyperlink = mbInHyperlink; 1580 pRdr->bWasParaEnd = mbWasParaEnd; 1581 pRdr->bPgSecBreak = mbPgSecBreak; 1582 pRdr->nAktColl = mnAktColl; 1583 pRdr->bHasBorder = mbHasBorder; 1584 pRdr->bFirstPara = mbFirstPara; 1585 1586 // schliesse alle Attribute, da sonst Attribute 1587 // entstehen koennen, die aus dem Fly rausragen 1588 pRdr->DeleteCtrlStk(); 1589 pRdr->pCtrlStck = mpOldStck; 1590 1591 pRdr->mpRedlineStack->closeall(*pRdr->pPaM->GetPoint()); 1592 delete pRdr->mpRedlineStack; 1593 pRdr->mpRedlineStack = mpOldRedlines; 1594 1595 pRdr->DeleteAnchorStk(); 1596 pRdr->pAnchorStck = mpOldAnchorStck; 1597 1598 *pRdr->pPaM->GetPoint() = maTmpPos; 1599 1600 if (mpOldPlcxMan != pRdr->pPlcxMan) 1601 { 1602 delete pRdr->pPlcxMan; 1603 pRdr->pPlcxMan = mpOldPlcxMan; 1604 } 1605 if (pRdr->pPlcxMan) 1606 pRdr->pPlcxMan->RestoreAllPLCFx(maPLCFxSave); 1607 pRdr->maApos.swap(maOldApos); 1608 pRdr->maFieldStack.swap(maOldFieldStack); 1609 } 1610 1611 void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex* pSttIdx, 1612 long nStartCp, long nLen, ManTypes nType ) 1613 { 1614 // rettet Flags u.ae. u. setzt sie zurueck 1615 WW8ReaderSave aSave( this ); 1616 1617 pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1; // 1618 pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 ); 1619 1620 // dann Text fuer Header, Footer o. Footnote einlesen 1621 1622 ReadText( nStartCp, nLen, nType ); // Sepx dabei ignorieren 1623 aSave.Restore( this ); 1624 } 1625 1626 //Use authornames, if not available fall back to initials. 1627 long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes) 1628 { 1629 WW8PLCFx_SubDoc* pSD = pPlcxMan->GetAtn(); 1630 if( !pSD ) 1631 return 0; 1632 1633 String sAuthor; 1634 if( bVer67 ) 1635 { 1636 const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData(); 1637 const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst)); 1638 if (pA) 1639 sAuthor = *pA; 1640 else 1641 sAuthor = String(pDescri->xstUsrInitl + 1, pDescri->xstUsrInitl[0], 1642 RTL_TEXTENCODING_MS_1252); 1643 } 1644 else 1645 { 1646 const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData(); 1647 1648 if (const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst))) 1649 sAuthor = *pA; 1650 else 1651 { 1652 sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]); 1653 for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx) 1654 sAuthor += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]); 1655 } 1656 } 1657 1658 sal_uInt32 nDateTime = 0; 1659 1660 if (sal_uInt8 * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments 1661 { 1662 sal_uLong nIndex = pSD->GetIdx() & 0xFFFF; //Index is (stupidly) multiplexed for WW8PLCFx_SubDocs 1663 if (pWwFib->lcbAtrdExtra/18 > nIndex) 1664 nDateTime = SVBT32ToUInt32(*(SVBT32*)(pExtended+(nIndex*18))); 1665 } 1666 1667 DateTime aDate = sw::ms::DTTM2DateTime(nDateTime); 1668 1669 String sTxt; 1670 OutlinerParaObject *pOutliner = ImportAsOutliner( sTxt, pRes->nCp2OrIdx, 1671 pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND ); 1672 1673 this->pFmtOfJustInsertedApo = 0; 1674 SwPostItField aPostIt( 1675 (SwPostItFieldType*)rDoc.GetSysFldType(RES_POSTITFLD), sAuthor, 1676 sTxt, aDate ); 1677 aPostIt.SetTextObject(pOutliner); 1678 1679 pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN)); 1680 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aPostIt), 0); 1681 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_HIDDEN); 1682 1683 return 0; 1684 } 1685 1686 void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen, 1687 SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth) 1688 { 1689 const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx(); 1690 ASSERT(pSttIdx, "impossible"); 1691 if (!pSttIdx) 1692 return; 1693 1694 SwPosition aTmpPos(*pPaM->GetPoint()); 1695 1696 pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1; 1697 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0); 1698 1699 SwFlyFrmFmt *pFrame = rDoc.MakeFlySection(FLY_AT_PARA, pPaM->GetPoint()); 1700 1701 SwFmtAnchor aAnch( pFrame->GetAnchor() ); 1702 aAnch.SetType( FLY_AT_PARA ); 1703 pFrame->SetFmtAttr( aAnch ); 1704 SwFmtFrmSize aSz(ATT_MIN_SIZE, nPageWidth, MINLAY); 1705 SwFrmSize eFrmSize = ATT_MIN_SIZE; 1706 if( eFrmSize != aSz.GetWidthSizeType() ) 1707 aSz.SetWidthSizeType( eFrmSize ); 1708 pFrame->SetFmtAttr(aSz); 1709 pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT)); 1710 pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::LEFT)); //iFOO 1711 1712 // #i43427# - send frame for header/footer into background. 1713 pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) ); 1714 SdrObject* pFrmObj = CreateContactObject( pFrame ); 1715 ASSERT( pFrmObj, 1716 "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" ); 1717 if ( pFrmObj ) 1718 { 1719 pFrmObj->SetOrdNum( 0L ); 1720 } 1721 MoveInsideFly(pFrame); 1722 1723 const SwNodeIndex* pHackIdx = pFrame->GetCntnt().GetCntntIdx(); 1724 1725 Read_HdFtFtnText(pHackIdx, nStart, nLen - 1, MAN_HDFT); 1726 1727 MoveOutsideFly(pFrame, aTmpPos); 1728 } 1729 1730 void SwWW8ImplReader::Read_HdFtText(long nStart, long nLen, SwFrmFmt* pHdFtFmt) 1731 { 1732 const SwNodeIndex* pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx(); 1733 if (!pSttIdx) 1734 return; 1735 1736 SwPosition aTmpPos( *pPaM->GetPoint() ); // merke alte Cursorposition 1737 1738 Read_HdFtFtnText(pSttIdx, nStart, nLen - 1, MAN_HDFT); 1739 1740 *pPaM->GetPoint() = aTmpPos; 1741 } 1742 1743 1744 bool SwWW8ImplReader::isValid_HdFt_CP(WW8_CP nHeaderCP) const 1745 { 1746 //each CP of Plcfhdd MUST be less than FibRgLw97.ccpHdd 1747 return (nHeaderCP < pWwFib->ccpHdr) ? true : false; 1748 } 1749 1750 bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems, sal_uInt8 grpfIhdt, 1751 int nSect) 1752 { 1753 if (pHdFt) 1754 { 1755 WW8_CP start; 1756 long nLen; 1757 sal_uInt8 nNumber = 5; 1758 1759 for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- ) 1760 { 1761 if (nI & nWhichItems) 1762 { 1763 bool bOk = true; 1764 if( bVer67 ) 1765 bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 ); 1766 else 1767 { 1768 pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen); 1769 bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start); 1770 } 1771 1772 if (bOk) 1773 return true; 1774 } 1775 } 1776 } 1777 return false; 1778 } 1779 1780 void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect, 1781 const SwPageDesc *pPrev, const wwSection &rSection) 1782 { 1783 sal_uInt8 nWhichItems = 0; 1784 SwPageDesc *pPD = 0; 1785 if (!bIsTitle) 1786 { 1787 nWhichItems = 1788 rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST); 1789 pPD = rSection.mpPage; 1790 } 1791 else 1792 { 1793 // Always read title page header/footer data - it could be used by following sections 1794 nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST ); 1795 pPD = rSection.mpTitlePage; 1796 } 1797 1798 sal_uInt8 grpfIhdt = rSection.maSep.grpfIhdt; 1799 1800 1801 if( pHdFt ) 1802 { 1803 WW8_CP start; 1804 long nLen; 1805 sal_uInt8 nNumber = 5; 1806 1807 for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- ) 1808 { 1809 if (nI & nWhichItems) 1810 { 1811 bool bOk = true; 1812 if( bVer67 ) 1813 bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 ); 1814 else 1815 { 1816 pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen); 1817 bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start); 1818 } 1819 1820 bool bUseLeft 1821 = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false; 1822 bool bFooter 1823 = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false; 1824 1825 SwFrmFmt* pFmt = bUseLeft ? &pPD->GetLeft() : &pPD->GetMaster(); 1826 1827 SwFrmFmt* pHdFtFmt; 1828 if (bFooter) 1829 { 1830 bIsFooter = true; 1831 //#i17196# Cannot have left without right 1832 if (!pPD->GetMaster().GetFooter().GetFooterFmt()) 1833 pPD->GetMaster().SetFmtAttr(SwFmtFooter(true)); 1834 if (bUseLeft) 1835 pPD->GetLeft().SetFmtAttr(SwFmtFooter(true)); 1836 pHdFtFmt = (SwFrmFmt*)pFmt->GetFooter().GetFooterFmt(); 1837 } 1838 else 1839 { 1840 bIsHeader = true; 1841 //#i17196# Cannot have left without right 1842 if (!pPD->GetMaster().GetHeader().GetHeaderFmt()) 1843 pPD->GetMaster().SetFmtAttr(SwFmtHeader(true)); 1844 if (bUseLeft) 1845 pPD->GetLeft().SetFmtAttr(SwFmtHeader(true)); 1846 pHdFtFmt = (SwFrmFmt*)pFmt->GetHeader().GetHeaderFmt(); 1847 } 1848 1849 if (bOk) 1850 { 1851 bool bHackRequired = false; 1852 if (bIsHeader && rSection.IsFixedHeightHeader()) 1853 bHackRequired = true; 1854 else if (bIsFooter && rSection.IsFixedHeightFooter()) 1855 bHackRequired = true; 1856 1857 if (bHackRequired) 1858 { 1859 Read_HdFtTextAsHackedFrame(start, nLen, *pHdFtFmt, 1860 static_cast< sal_uInt16 >(rSection.GetTextAreaWidth()) ); 1861 } 1862 else 1863 Read_HdFtText(start, nLen, pHdFtFmt); 1864 } 1865 else if (!bOk && pPrev) 1866 CopyPageDescHdFt(pPrev, pPD, nI); 1867 1868 bIsHeader = bIsFooter = false; 1869 } 1870 } 1871 } 1872 maTracer.LeaveEnvironment(sw::log::eDocumentProperties); 1873 } 1874 1875 bool wwSectionManager::SectionIsProtected(const wwSection &rSection) const 1876 { 1877 return (mrReader.pWwFib->fReadOnlyRecommended && !rSection.IsNotProtected()); 1878 } 1879 1880 void wwSectionManager::SetHdFt(wwSection &rSection, int nSect, 1881 const wwSection *pPrevious) 1882 { 1883 // Header / Footer nicht da 1884 if (!rSection.maSep.grpfIhdt) 1885 return; 1886 1887 ASSERT(rSection.mpPage, "makes no sense to call with a main page"); 1888 if (rSection.mpPage) 1889 { 1890 mrReader.Read_HdFt(false, nSect, pPrevious ? pPrevious->mpPage : 0, 1891 rSection); 1892 } 1893 1894 if (rSection.mpTitlePage) 1895 { 1896 // 2 Pagedescs noetig: 1.Seite und folgende 1897 // 1. Seite einlesen 1898 mrReader.Read_HdFt(true, nSect, pPrevious ? pPrevious->mpTitlePage : 0, 1899 rSection); 1900 } 1901 1902 // Kopf / Fuss - Index Updaten 1903 // Damit der Index auch spaeter noch stimmt 1904 if (mrReader.pHdFt) 1905 mrReader.pHdFt->UpdateIndex(rSection.maSep.grpfIhdt); 1906 1907 } 1908 1909 class AttribHere : public std::unary_function<const xub_StrLen*, bool> 1910 { 1911 private: 1912 xub_StrLen nPosition; 1913 public: 1914 AttribHere(xub_StrLen nPos) : nPosition(nPos) {} 1915 bool operator()(const xub_StrLen *pPosition) const 1916 { 1917 return (*pPosition >= nPosition); 1918 } 1919 }; 1920 1921 void SwWW8ImplReader::AppendTxtNode(SwPosition& rPos) 1922 { 1923 SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode(); 1924 1925 const SwNumRule* pRule = NULL; 1926 1927 if (pTxt != NULL) 1928 pRule = sw::util::GetNumRuleFromTxtNode(*pTxt); 1929 1930 if ( 1931 pRule && !pWDop->fDontUseHTMLAutoSpacing && 1932 (bParaAutoBefore || bParaAutoAfter) 1933 ) 1934 { 1935 // If after spacing is set to auto, set the after space to 0 1936 if (bParaAutoAfter) 1937 SetLowerSpacing(*pPaM, 0); 1938 1939 // If the previous textnode had numbering and 1940 // and before spacing is set to auto, set before space to 0 1941 if(pPrevNumRule && bParaAutoBefore) 1942 SetUpperSpacing(*pPaM, 0); 1943 1944 // If the previous numbering rule was different we need 1945 // to insert a space after the previous paragraph 1946 if((pRule != pPrevNumRule) && pPreviousNumPaM) 1947 SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing)); 1948 1949 // cache current paragraph 1950 if(pPreviousNumPaM) 1951 delete pPreviousNumPaM, pPreviousNumPaM = 0; 1952 1953 pPreviousNumPaM = new SwPaM(*pPaM); 1954 pPrevNumRule = pRule; 1955 } 1956 else if(!pRule && pPreviousNumPaM) 1957 { 1958 // If the previous paragraph has numbering but the current one does not 1959 // we need to add a space after the previous paragraph 1960 SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing)); 1961 delete pPreviousNumPaM, pPreviousNumPaM = 0; 1962 pPrevNumRule = 0; 1963 } 1964 else 1965 { 1966 // clear paragraph cache 1967 if(pPreviousNumPaM) 1968 delete pPreviousNumPaM, pPreviousNumPaM = 0; 1969 pPrevNumRule = pRule; 1970 } 1971 1972 // If this is the first paragraph in the document and 1973 // Auto-spacing before paragraph is set, 1974 // set the upper spacing value to 0 1975 if(bParaAutoBefore && bFirstPara && !pWDop->fDontUseHTMLAutoSpacing) 1976 SetUpperSpacing(*pPaM, 0); 1977 1978 bFirstPara = false; 1979 1980 rDoc.AppendTxtNode(rPos); 1981 1982 //We can flush all anchored graphics at the end of a paragraph. 1983 pAnchorStck->Flush(); 1984 } 1985 1986 bool SwWW8ImplReader::SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper ) 1987 { 1988 bool bRet = false; 1989 const SwPosition* pSpacingPos = rMyPam.GetPoint(); 1990 1991 const SvxULSpaceItem* pULSpaceItem = (const SvxULSpaceItem*)pCtrlStck->GetFmtAttr(*pSpacingPos, RES_UL_SPACE); 1992 1993 if(pULSpaceItem != 0) 1994 { 1995 SvxULSpaceItem aUL(*pULSpaceItem); 1996 1997 if(bIsUpper) 1998 aUL.SetUpper( static_cast< sal_uInt16 >(nSpace) ); 1999 else 2000 aUL.SetLower( static_cast< sal_uInt16 >(nSpace) ); 2001 2002 xub_StrLen nEnd = pSpacingPos->nContent.GetIndex(); 2003 rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), 0); 2004 pCtrlStck->NewAttr(*pSpacingPos, aUL); 2005 rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), nEnd); 2006 pCtrlStck->SetAttr(*pSpacingPos, RES_UL_SPACE); 2007 bRet = true; 2008 } 2009 return bRet; 2010 } 2011 2012 bool SwWW8ImplReader::SetLowerSpacing(SwPaM &rMyPam, int nSpace) 2013 { 2014 return SetSpacing(rMyPam, nSpace, false); 2015 } 2016 2017 bool SwWW8ImplReader::SetUpperSpacing(SwPaM &rMyPam, int nSpace) 2018 { 2019 return SetSpacing(rMyPam, nSpace, true); 2020 } 2021 2022 sal_uInt16 SwWW8ImplReader::TabRowSprm(int nLevel) const 2023 { 2024 if (bVer67) 2025 return 25; 2026 return nLevel ? 0x244C : 0x2417; 2027 } 2028 2029 void SwWW8ImplReader::EndSpecial() 2030 { 2031 // Frame / Table / Anl 2032 if (bAnl) 2033 StopAllAnl(); // -> bAnl = false 2034 2035 while(maApos.size() > 1) 2036 { 2037 StopTable(); 2038 maApos.pop_back(); 2039 --nInTable; 2040 if (maApos[nInTable] == true) 2041 StopApo(); 2042 } 2043 2044 if (maApos[0] == true) 2045 StopApo(); 2046 2047 ASSERT(!nInTable, "unclosed table!"); 2048 } 2049 2050 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp) 2051 { 2052 // Frame / Table / Anl 2053 if (bInHyperlink) 2054 return false; 2055 2056 rbReSync = false; 2057 2058 ASSERT(nInTable >= 0,"nInTable < 0!"); 2059 2060 // TabRowEnd 2061 bool bTableRowEnd = (pPlcxMan->HasParaSprm(bVer67 ? 25 : 0x2417) != 0 ); 2062 2063 // es muss leider fuer jeden Absatz zuerst nachgesehen werden, 2064 // ob sich unter den sprms 2065 // das sprm 29 (bzw. 0x261B) befindet, das ein APO einleitet. 2066 // Alle weiteren sprms beziehen sich dann naemlich auf das APO und nicht 2067 // auf den normalen Text drumrum. 2068 // Dasselbe gilt fuer eine Tabelle ( sprm 24 (bzw. 0x2416) ) 2069 // und Anls ( sprm 13 ). 2070 // WW: Tabelle in APO geht ( Beide Anfaende treten gleichzeitig auf ) 2071 // WW: APO in Tabelle geht nicht 2072 // d.h. Wenn eine Tabelle Inhalt eines Apo ist, dann muss der 2073 // Apo-Anfang zuerst bearbeitet werden, damit die Tabelle im Apo steht 2074 // und nicht umgekehrt. Am Ende muss dagegen zuerst das Tabellenende 2075 // bearbeitet werden, da die Apo erst nach der Tabelle abgeschlossen 2076 // werden darf ( sonst wird das Apo-Ende nie gefunden ). 2077 // Dasselbe gilt fuer Fly / Anl, Tab / Anl, Fly / Tab / Anl. 2078 // 2079 // Wenn die Tabelle in einem Apo steht, fehlen im TabRowEnd-Bereich 2080 // die Apo-Angaben. Damit hier die Apo nicht beendet wird, wird 2081 // ProcessApo dann nicht aufgerufen. 2082 2083 // KHZ: When there is a table inside the Apo the Apo-flags are also 2084 // missing for the 2nd, 3rd... paragraphs of each cell. 2085 2086 2087 // 1st look for in-table flag, for 2000+ there is a subtable flag to 2088 // be considered, the sprm 6649 gives the level of the table 2089 sal_uInt8 nCellLevel = 0; 2090 2091 if (bVer67) 2092 nCellLevel = 0 != pPlcxMan->HasParaSprm(24); 2093 else 2094 { 2095 nCellLevel = 0 != pPlcxMan->HasParaSprm(0x2416); 2096 if (!nCellLevel) 2097 nCellLevel = 0 != pPlcxMan->HasParaSprm(0x244B); 2098 } 2099 2100 WW8_TablePos *pTabPos=0; 2101 WW8_TablePos aTabPos; 2102 if (nCellLevel && !bVer67) 2103 { 2104 WW8PLCFxSave1 aSave; 2105 pPlcxMan->GetPap()->Save( aSave ); 2106 rbReSync = true; 2107 WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF(); 2108 WW8_CP nMyStartCp=nStartCp; 2109 2110 if (const sal_uInt8 *pLevel = pPlcxMan->HasParaSprm(0x6649)) 2111 nCellLevel = *pLevel; 2112 2113 bool bHasRowEnd = SearchRowEnd(pPap, nMyStartCp, nCellLevel-1); 2114 2115 //Bad Table, remain unchanged in level, e.g. #i19667# 2116 if (!bHasRowEnd) 2117 nCellLevel = static_cast< sal_uInt8 >(nInTable); 2118 2119 if (bHasRowEnd && ParseTabPos(&aTabPos,pPap)) 2120 pTabPos = &aTabPos; 2121 2122 pPlcxMan->GetPap()->Restore( aSave ); 2123 } 2124 2125 // then look if we are in an Apo 2126 2127 ApoTestResults aApo = TestApo(nCellLevel, bTableRowEnd, pTabPos); 2128 2129 //look to see if we are in a Table, but Table in foot/end note not allowed 2130 bool bStartTab = (nInTable < nCellLevel) && !bFtnEdn; 2131 2132 bool bStopTab = bWasTabRowEnd && (nInTable > nCellLevel) && !bFtnEdn; 2133 2134 bWasTabRowEnd = false; // must be deactivated right here to prevent next 2135 // WW8TabDesc::TableCellEnd() from making nonsense 2136 2137 if (nInTable && !bTableRowEnd && !bStopTab && (nInTable == nCellLevel && aApo.HasStartStop())) 2138 bStopTab = bStartTab = true; // Required to stop and start table 2139 2140 // Dann auf Anl (Nummerierung) testen 2141 // und dann alle Ereignisse in der richtigen Reihenfolge bearbeiten 2142 2143 if( bAnl && !bTableRowEnd ) 2144 { 2145 const sal_uInt8* pSprm13 = pPlcxMan->HasParaSprm( 13 ); 2146 if( pSprm13 ) 2147 { // Noch Anl ? 2148 sal_uInt8 nT = static_cast< sal_uInt8 >(GetNumType( *pSprm13 )); 2149 if( ( nT != WW8_Pause && nT != nWwNumType ) // Anl-Wechsel 2150 || aApo.HasStartStop() // erzwungenes Anl-Ende 2151 || bStopTab || bStartTab ) 2152 { 2153 StopAnlToRestart(nT); // Anl-Restart ( = Wechsel ) ueber sprms 2154 } 2155 else 2156 { 2157 NextAnlLine( pSprm13 ); // naechste Anl-Zeile 2158 } 2159 } 2160 else 2161 { // Anl normal zuende 2162 StopAllAnl(); // Wirkliches Ende 2163 } 2164 } 2165 if (bStopTab) 2166 { 2167 StopTable(); 2168 maApos.pop_back(); 2169 --nInTable; 2170 } 2171 if (aApo.mbStopApo) 2172 { 2173 StopApo(); 2174 maApos[nInTable] = false; 2175 } 2176 2177 if (aApo.mbStartApo) 2178 { 2179 maApos[nInTable] = StartApo(aApo, pTabPos); 2180 // nach StartApo ist ein ReSync noetig ( eigentlich nur, falls die Apo 2181 // ueber eine FKP-Grenze geht 2182 rbReSync = true; 2183 } 2184 if (bStartTab) 2185 { 2186 WW8PLCFxSave1 aSave; 2187 pPlcxMan->GetPap()->Save( aSave ); 2188 2189 if (bAnl) // Nummerierung ueber Zellengrenzen 2190 StopAllAnl(); // fuehrt zu Absturz -> keine Anls 2191 // in Tabellen 2192 while (nInTable < nCellLevel) 2193 { 2194 if (StartTable(nStartCp)) 2195 ++nInTable; 2196 else 2197 break; 2198 2199 maApos.push_back(false); 2200 } 2201 // nach StartTable ist ein ReSync noetig ( eigentlich nur, falls die 2202 // Tabelle ueber eine FKP-Grenze geht 2203 rbReSync = true; 2204 pPlcxMan->GetPap()->Restore( aSave ); 2205 } 2206 return bTableRowEnd; 2207 } 2208 2209 CharSet SwWW8ImplReader::GetCurrentCharSet() 2210 { 2211 /* 2212 #i2015 2213 If the hard charset is set use it, if not see if there is an open 2214 character run that has set the charset, if not then fallback to the 2215 current underlying paragraph style. 2216 */ 2217 CharSet eSrcCharSet = eHardCharSet; 2218 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) 2219 { 2220 if (!maFontSrcCharSets.empty()) 2221 eSrcCharSet = maFontSrcCharSets.top(); 2222 if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1)) 2223 eSrcCharSet = pCollA[nCharFmt].GetCharSet(); 2224 if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && StyleExists(nAktColl)) 2225 eSrcCharSet = pCollA[nAktColl].GetCharSet(); 2226 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) 2227 { // patch from cmc for #i52786# 2228 /* 2229 #i22206#/#i52786# 2230 The (default) character set used for a run of text is the default 2231 character set for the version of Word that last saved the document. 2232 2233 This is a bit tentative, more might be required if the concept is correct. 2234 When later version of word write older 6/95 documents the charset is 2235 correctly set in the character runs involved, so its hard to reproduce 2236 documents that require this to be sure of the process involved. 2237 */ 2238 const SvxLanguageItem *pLang = 2239 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE); 2240 if (pLang) 2241 { 2242 switch (pLang->GetLanguage()) 2243 { 2244 case LANGUAGE_CZECH: 2245 case LANGUAGE_HUNGARIAN: 2246 case LANGUAGE_POLISH: 2247 eSrcCharSet = RTL_TEXTENCODING_MS_1250; 2248 break; 2249 case LANGUAGE_RUSSIAN: 2250 eSrcCharSet = RTL_TEXTENCODING_MS_1251; 2251 break; 2252 case LANGUAGE_GREEK: 2253 eSrcCharSet = RTL_TEXTENCODING_MS_1253; 2254 break; 2255 case LANGUAGE_TURKISH: 2256 eSrcCharSet = RTL_TEXTENCODING_MS_1254; 2257 break; 2258 default: 2259 eSrcCharSet = RTL_TEXTENCODING_MS_1252; 2260 break; 2261 } 2262 } 2263 } 2264 } 2265 return eSrcCharSet; 2266 } 2267 2268 //Takashi Ono for CJK 2269 CharSet SwWW8ImplReader::GetCurrentCJKCharSet() 2270 { 2271 /* 2272 #i2015 2273 If the hard charset is set use it, if not see if there is an open 2274 character run that has set the charset, if not then fallback to the 2275 current underlying paragraph style. 2276 */ 2277 CharSet eSrcCharSet = eHardCharSet; 2278 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) 2279 { 2280 if (!maFontSrcCJKCharSets.empty()) 2281 eSrcCharSet = maFontSrcCJKCharSets.top(); 2282 if (pCollA != NULL) 2283 { 2284 if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1)) 2285 eSrcCharSet = pCollA[nCharFmt].GetCJKCharSet(); 2286 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) 2287 eSrcCharSet = pCollA[nAktColl].GetCJKCharSet(); 2288 } 2289 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) 2290 { // patch from cmc for #i52786# 2291 /* 2292 #i22206#/#i52786# 2293 The (default) character set used for a run of text is the default 2294 character set for the version of Word that last saved the document. 2295 2296 This is a bit tentative, more might be required if the concept is correct. 2297 When later version of word write older 6/95 documents the charset is 2298 correctly set in the character runs involved, so its hard to reproduce 2299 documents that require this to be sure of the process involved. 2300 */ 2301 const SvxLanguageItem *pLang = 2302 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE); 2303 if (pLang) 2304 { 2305 switch (pLang->GetLanguage()) 2306 { 2307 case LANGUAGE_CZECH: 2308 eSrcCharSet = RTL_TEXTENCODING_MS_1250; 2309 break; 2310 default: 2311 eSrcCharSet = RTL_TEXTENCODING_MS_1252; 2312 break; 2313 } 2314 } 2315 } 2316 } 2317 return eSrcCharSet; 2318 } 2319 2320 void SwWW8ImplReader::PostProcessAttrs() 2321 { 2322 if (mpPostProcessAttrsInfo != NULL) 2323 { 2324 SfxItemIter aIter(mpPostProcessAttrsInfo->mItemSet); 2325 2326 const SfxPoolItem * pItem = aIter.GetCurItem(); 2327 if (pItem != NULL) 2328 { 2329 do 2330 { 2331 pCtrlStck->NewAttr(*mpPostProcessAttrsInfo->mPaM.GetPoint(), 2332 *pItem); 2333 pCtrlStck->SetAttr(*mpPostProcessAttrsInfo->mPaM.GetMark(), 2334 pItem->Which(), true); 2335 } 2336 while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem())); 2337 } 2338 2339 delete mpPostProcessAttrsInfo; 2340 mpPostProcessAttrsInfo = NULL; 2341 } 2342 } 2343 2344 /* 2345 #i9241# 2346 It appears that some documents that are in a baltic 8 bit encoding which has 2347 some undefined characters can have use made of those characters, in which 2348 case they default to CP1252. If not then its perhaps that the font encoding 2349 is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding 2350 is always 1252. 2351 2352 So a encoding converter that on an undefined character attempts to 2353 convert from 1252 on the undefined character 2354 */ 2355 sal_Size Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter, 2356 sal_Char *pIn, sal_Size nInLen, sal_Unicode *pOut, sal_Size nOutLen) 2357 { 2358 const sal_uInt32 nFlags = 2359 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR | 2360 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR | 2361 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE | 2362 RTL_TEXTTOUNICODE_FLAGS_FLUSH; 2363 2364 const sal_uInt32 nFlags2 = 2365 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE | 2366 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE | 2367 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE | 2368 RTL_TEXTTOUNICODE_FLAGS_FLUSH; 2369 2370 sal_Size nDestChars=0; 2371 sal_Size nConverted=0; 2372 2373 do 2374 { 2375 sal_uInt32 nInfo = 0; 2376 sal_Size nThisConverted=0; 2377 2378 nDestChars += rtl_convertTextToUnicode(hConverter, 0, 2379 pIn+nConverted, nInLen-nConverted, 2380 pOut+nDestChars, nOutLen-nDestChars, 2381 nFlags, &nInfo, &nThisConverted); 2382 2383 ASSERT(nInfo == 0, "A character conversion failed!"); 2384 2385 nConverted += nThisConverted; 2386 2387 if ( 2388 nInfo & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR || 2389 nInfo & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR 2390 ) 2391 { 2392 sal_Size nOtherConverted; 2393 rtl_TextToUnicodeConverter hCP1252Converter = 2394 rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252); 2395 nDestChars += rtl_convertTextToUnicode(hCP1252Converter, 0, 2396 pIn+nConverted, 1, 2397 pOut+nDestChars, nOutLen-nDestChars, 2398 nFlags2, &nInfo, &nOtherConverted); 2399 rtl_destroyTextToUnicodeConverter(hCP1252Converter); 2400 nConverted+=1; 2401 } 2402 } while (nConverted < nInLen); 2403 2404 return nDestChars; 2405 } 2406 2407 bool SwWW8ImplReader::LangUsesHindiNumbers(sal_uInt16 nLang) 2408 { 2409 bool bResult = false; 2410 2411 switch (nLang) 2412 { 2413 case 0x1401: // Arabic(Algeria) 2414 case 0x3c01: // Arabic(Bahrain) 2415 case 0xc01: // Arabic(Egypt) 2416 case 0x801: // Arabic(Iraq) 2417 case 0x2c01: // Arabic (Jordan) 2418 case 0x3401: // Arabic(Kuwait) 2419 case 0x3001: // Arabic(Lebanon) 2420 case 0x1001: // Arabic(Libya) 2421 case 0x1801: // Arabic(Morocco) 2422 case 0x2001: // Arabic(Oman) 2423 case 0x4001: // Arabic(Qatar) 2424 case 0x401: // Arabic(Saudi Arabia) 2425 case 0x2801: // Arabic(Syria) 2426 case 0x1c01: // Arabic(Tunisia) 2427 case 0x3801: // Arabic(U.A.E) 2428 case 0x2401: // Arabic(Yemen) 2429 bResult = true; 2430 break; 2431 default: 2432 break; 2433 } 2434 2435 return bResult; 2436 } 2437 2438 sal_Unicode SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar) 2439 { 2440 if (nChar >= 0x0030 && nChar <= 0x0039) 2441 return nChar + 0x0630; 2442 2443 return nChar; 2444 } 2445 2446 // Returnwert: true for no Sonderzeichen 2447 bool SwWW8ImplReader::ReadPlainChars(WW8_CP& rPos, long nEnd, long nCpOfs) 2448 { 2449 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren 2450 // merke: Seek kostet nicht viel, da inline geprueft wird, 2451 // ob die korrekte FilePos nicht schon erreicht ist. 2452 WW8_FC nStreamPos = pSBase->WW8Cp2Fc(nCpOfs+rPos, &bIsUnicode); 2453 pStrm->Seek( nStreamPos ); 2454 2455 xub_StrLen nLen; 2456 if (nEnd - rPos <= (STRING_MAXLEN-1)) 2457 nLen = writer_cast<xub_StrLen>(nEnd - rPos); 2458 else 2459 nLen = STRING_MAXLEN-1; 2460 ASSERT(nLen, "String is 0"); 2461 if (!nLen) 2462 return true; 2463 2464 const CharSet eSrcCharSet = bVer67 ? GetCurrentCharSet() : 2465 RTL_TEXTENCODING_MS_1252; 2466 const CharSet eSrcCJKCharSet = bVer67 ? GetCurrentCJKCharSet() : 2467 RTL_TEXTENCODING_MS_1252; 2468 2469 // (re)alloc UniString data 2470 String sPlainCharsBuf; 2471 2472 sal_Unicode* pBuffer = sPlainCharsBuf.AllocBuffer( nLen ); 2473 sal_Unicode* pWork = pBuffer; 2474 2475 sal_Char* p8Bits = NULL; 2476 2477 rtl_TextToUnicodeConverter hConverter = 0; 2478 if (!bIsUnicode || bVer67) 2479 hConverter = rtl_createTextToUnicodeConverter(eSrcCharSet); 2480 2481 if (!bIsUnicode) 2482 p8Bits = new sal_Char[nLen]; 2483 2484 // read the stream data 2485 sal_uInt8 nBCode = 0; 2486 sal_uInt16 nUCode; 2487 xub_StrLen nL2; 2488 2489 sal_uInt16 nCTLLang = 0; 2490 const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CTL_LANGUAGE); 2491 if (pItem != NULL) 2492 nCTLLang = dynamic_cast<const SvxLanguageItem *>(pItem)->GetLanguage(); 2493 2494 for( nL2 = 0; nL2 < nLen; ++nL2, ++pWork ) 2495 { 2496 if (bIsUnicode) 2497 *pStrm >> nUCode; // unicode --> read 2 bytes 2498 else 2499 { 2500 *pStrm >> nBCode; // old code --> read 1 byte 2501 nUCode = nBCode; 2502 } 2503 2504 if (pStrm->GetError()) 2505 { 2506 rPos = WW8_CP_MAX-10; // -> eof or other error 2507 sPlainCharsBuf.ReleaseBufferAccess( 0 ); 2508 delete [] p8Bits; 2509 return true; 2510 } 2511 2512 if ((32 > nUCode) || (0xa0 == nUCode)) 2513 { 2514 pStrm->SeekRel( bIsUnicode ? -2 : -1 ); 2515 break; // Sonderzeichen < 32, == 0xa0 gefunden 2516 } 2517 2518 if (bIsUnicode) 2519 { 2520 if (!bVer67) 2521 *pWork = nUCode; 2522 else 2523 { 2524 if (nUCode >= 0x3000) //0x8000 ? 2525 { 2526 sal_Char aTest[2]; 2527 aTest[0] = static_cast< sal_Char >((nUCode & 0xFF00) >> 8); 2528 aTest[1] = static_cast< sal_Char >(nUCode & 0x00FF); 2529 String aTemp(aTest, 2, eSrcCJKCharSet); 2530 ASSERT(aTemp.Len() == 1, "so much for that theory"); 2531 *pWork = aTemp.GetChar(0); 2532 } 2533 else 2534 { 2535 sal_Char cTest = static_cast< sal_Char >(nUCode & 0x00FF); 2536 Custom8BitToUnicode(hConverter, &cTest, 1, pWork, 1); 2537 } 2538 } 2539 } 2540 else 2541 p8Bits[nL2] = nBCode; 2542 } 2543 2544 if (nL2) 2545 { 2546 xub_StrLen nEndUsed = nL2; 2547 2548 if (!bIsUnicode) 2549 nEndUsed = Custom8BitToUnicode(hConverter, p8Bits, nL2, pBuffer, nLen); 2550 2551 for( xub_StrLen nI = 0; nI < nLen; ++nI, ++pBuffer ) 2552 if (m_bRegardHindiDigits && bBidi && LangUsesHindiNumbers(nCTLLang)) 2553 *pBuffer = TranslateToHindiNumbers(*pBuffer); 2554 2555 sPlainCharsBuf.ReleaseBufferAccess( nEndUsed ); 2556 2557 AddTextToParagraph(sPlainCharsBuf); 2558 rPos += nL2; 2559 if (!maApos.back()) //a para end in apo doesn't count 2560 bWasParaEnd = false; //kein CR 2561 } 2562 2563 if (hConverter) 2564 rtl_destroyTextToUnicodeConverter(hConverter); 2565 delete [] p8Bits; 2566 return nL2 >= nLen; 2567 } 2568 2569 bool SwWW8ImplReader::AddTextToParagraph(const String& rAddString) 2570 { 2571 const SwTxtNode* pNd = pPaM->GetCntntNode()->GetTxtNode(); 2572 if (rAddString.Len()) 2573 { 2574 /* 2575 #ifdef DEBUG 2576 //!! does not compile with debug=t -> unresolved external (dbg_out), 2577 //!! sommeone who knows what he wants to get should fix this 2578 // ::std::clog << "<addTextToParagraph>" << dbg_out(rAddString) 2579 // << "</addTextToParagraph>" << ::std::endl; 2580 #endif 2581 */ 2582 if ((pNd->GetTxt().Len() + rAddString.Len()) < STRING_MAXLEN -1) 2583 { 2584 rDoc.InsertString(*pPaM, rAddString); 2585 } 2586 else 2587 { 2588 2589 if (pNd->GetTxt().Len()< STRING_MAXLEN -1) 2590 { 2591 String sTempStr (rAddString,0, 2592 STRING_MAXLEN - pNd->GetTxt().Len() -1); 2593 rDoc.InsertString(*pPaM, sTempStr); 2594 sTempStr = rAddString.Copy(sTempStr.Len(), 2595 rAddString.Len() - sTempStr.Len()); 2596 AppendTxtNode(*pPaM->GetPoint()); 2597 rDoc.InsertString(*pPaM, sTempStr); 2598 } 2599 else 2600 { 2601 AppendTxtNode(*pPaM->GetPoint()); 2602 rDoc.InsertString(*pPaM, rAddString); 2603 } 2604 } 2605 2606 bReadTable = false; 2607 } 2608 2609 return true; 2610 } 2611 2612 // Returnwert: true for para end 2613 bool SwWW8ImplReader::ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd, 2614 long nCpOfs) 2615 { 2616 long nEnd = ( nNextAttr < nTextEnd ) ? nNextAttr : nTextEnd; 2617 2618 if (bSymbol || bIgnoreText) 2619 { 2620 if( bSymbol ) // Spezialzeichen einfuegen 2621 { 2622 for(sal_uInt16 nCh = 0; nCh < nEnd - rPos; ++nCh) 2623 { 2624 rDoc.InsertString( *pPaM, cSymbol ); 2625 } 2626 pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT ); 2627 } 2628 pStrm->SeekRel( nEnd- rPos ); 2629 rPos = nEnd; // ignoriere bis Attributende 2630 return false; 2631 } 2632 2633 while (true) 2634 { 2635 if (ReadPlainChars(rPos, nEnd, nCpOfs)) 2636 return false; // Fertig 2637 2638 bool bStartLine = ReadChar(rPos, nCpOfs); 2639 rPos++; 2640 if (bPgSecBreak || bStartLine || rPos == nEnd) // CR oder Fertig 2641 { 2642 return bStartLine; 2643 } 2644 } 2645 } 2646 2647 bool SwWW8ImplReader::HandlePageBreakChar() 2648 { 2649 bool bParaEndAdded = false; 2650 //#i1909# section/page breaks should not occur in tables, word 2651 //itself ignores them in this case. 2652 if (!nInTable) 2653 { 2654 //xushanchuan add for issue106569 2655 sal_Bool IsTemp=sal_True; 2656 SwTxtNode* pTemp = pPaM->GetNode()->GetTxtNode(); 2657 if ( pTemp && !( pTemp->GetTxt().Len() ) && ( bFirstPara || bFirstParaOfPage ) ) 2658 { 2659 IsTemp = sal_False; 2660 AppendTxtNode(*pPaM->GetPoint()); 2661 pTemp->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE)); 2662 } 2663 //xushanchuan end 2664 bPgSecBreak = true; 2665 pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint()); 2666 /* 2667 If its a 0x0c without a paragraph end before it, act like a 2668 paragraph end, but nevertheless, numbering (and perhaps other 2669 similiar constructs) do not exist on the para. 2670 */ 2671 //xushanchuan add for issue106569 2672 if (!bWasParaEnd && IsTemp) 2673 //xushanchuan end 2674 { 2675 bParaEndAdded = true; 2676 if (0 >= pPaM->GetPoint()->nContent.GetIndex()) 2677 { 2678 if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode()) 2679 { 2680 pTxtNode->SetAttr( 2681 *GetDfltAttr(RES_PARATR_NUMRULE)); 2682 } 2683 } 2684 } 2685 } 2686 return bParaEndAdded; 2687 } 2688 2689 bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs) 2690 { 2691 bool bNewParaEnd = false; 2692 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren 2693 // merke: Seek kostet nicht viel, da inline geprueft wird, 2694 // ob die korrekte FilePos nicht schon erreicht ist. 2695 pStrm->Seek( pSBase->WW8Cp2Fc(nCpOfs+nPosCp, &bIsUnicode) ); 2696 2697 sal_uInt8 nBCode; 2698 sal_uInt16 nWCharVal; 2699 if( bIsUnicode ) 2700 *pStrm >> nWCharVal; // unicode --> read 2 bytes 2701 else 2702 { 2703 *pStrm >> nBCode; // old code --> read 1 byte 2704 nWCharVal = nBCode; 2705 } 2706 2707 sal_Char cInsert = '\x0'; 2708 bool bRet = false; 2709 //xushanchuan add for issue106569 2710 if ( 0xc != nWCharVal ) 2711 bFirstParaOfPage = false; 2712 //xushanchuan end 2713 switch (nWCharVal) 2714 { 2715 case 0: 2716 { 2717 // Seitennummer 2718 SwPageNumberField aFld( 2719 (SwPageNumberFieldType*)rDoc.GetSysFldType( 2720 RES_PAGENUMBERFLD ), PG_RANDOM, SVX_NUM_ARABIC); 2721 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0); 2722 } 2723 break; 2724 case 0xe: 2725 // if there is only one column word treats a column break like a pagebreak. 2726 if (maSectionManager.CurrentSectionColCount() < 2) 2727 bRet = HandlePageBreakChar(); 2728 else if (!nInTable) 2729 { 2730 // Always insert a txtnode for a column break, e.g. ## 2731 AppendTxtNode(*pPaM->GetPoint()); 2732 rDoc.InsertPoolItem(*pPaM, 2733 SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0); 2734 } 2735 break; 2736 case 0x7: 2737 bNewParaEnd = true; 2738 TabCellEnd(); // table cell end (Flags abfragen!) 2739 break; 2740 case 0xf: 2741 if( !bSpec ) // "Satellit" 2742 cInsert = '\xa4'; 2743 break; 2744 case 0x14: 2745 if( !bSpec ) // "Para-Ende"-Zeichen 2746 cInsert = '\xb5'; 2747 break; 2748 case 0x15: 2749 if( !bSpec ) // Juristenparagraph 2750 { 2751 cp_set::iterator aItr = maTOXEndCps.find((WW8_CP)nPosCp); 2752 if (aItr == maTOXEndCps.end()) 2753 cInsert = '\xa7'; 2754 else 2755 maTOXEndCps.erase(aItr); 2756 } 2757 break; 2758 case 0x9: 2759 cInsert = '\x9'; // Tab 2760 break; 2761 case 0xb: 2762 cInsert = '\xa'; // Hard NewLine 2763 break; 2764 case 0xc: 2765 bRet = HandlePageBreakChar(); 2766 break; 2767 case 0x1e: // Non-breaking hyphen 2768 rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN ); 2769 break; 2770 case 0x1f: // Non-required hyphens 2771 rDoc.InsertString( *pPaM, CHAR_SOFTHYPHEN ); 2772 break; 2773 case 0xa0: // Non-breaking spaces 2774 rDoc.InsertString( *pPaM, CHAR_HARDBLANK ); 2775 break; 2776 case 0x1: 2777 /* 2778 Current thinking is that if bObj is set then we have a 2779 straightforward "traditional" ole object, otherwise we have a 2780 graphic preview of an associated ole2 object (or a simple 2781 graphic of course) 2782 */ 2783 //normally in the canvas field, the code is 0x8 0x1. 2784 //in a special case, the code is 0x1 0x1, which yields a simple picture 2785 { 2786 bool bReadObj = IsInlineEscherHack(); 2787 if( bReadObj ) 2788 { 2789 long nCurPos = pStrm->Tell(); 2790 sal_uInt8 nByteCode; 2791 sal_uInt16 nWordCode; 2792 2793 if( bIsUnicode ) 2794 *pStrm >> nWordCode; 2795 else 2796 { 2797 *pStrm >> nByteCode; 2798 nWordCode = nByteCode; 2799 } 2800 if( nWordCode == 0x1 ) 2801 bReadObj = false; 2802 pStrm->Seek( nCurPos ); 2803 } 2804 if( !bReadObj ) 2805 { 2806 SwFrmFmt *pResult = 0; 2807 if (bObj) 2808 pResult = ImportOle(); 2809 else if (bSpec) 2810 pResult = ImportGraf(); 2811 2812 // If we have a bad 0x1 insert a space instead. 2813 if (!pResult) 2814 { 2815 cInsert = ' '; 2816 ASSERT(!bObj && !bEmbeddObj && !nObjLocFc, 2817 "WW8: Please report this document, it may have a " 2818 "missing graphic"); 2819 } 2820 else 2821 { 2822 // reset the flags. 2823 bObj = bEmbeddObj = false; 2824 nObjLocFc = 0; 2825 } 2826 } 2827 } 2828 break; 2829 case 0x8: 2830 if( !bObj ) 2831 Read_GrafLayer( nPosCp ); 2832 break; 2833 case 0xd: 2834 bNewParaEnd = bRet = true; 2835 if (nInTable > 1) 2836 { 2837 /* 2838 #i9666#/#i23161# 2839 Yes complex, if there is an entry in the undocumented PLCF 2840 which I believe to be a record of cell and row boundaries 2841 see if the magic bit which I believe to mean cell end is 2842 set. I also think btw that the third byte of the 4 byte 2843 value is the level of the cell 2844 */ 2845 WW8PLCFspecial* pTest = pPlcxMan->GetMagicTables(); 2846 if (pTest && pTest->SeekPosExact(nPosCp+1+nCpOfs) && 2847 pTest->Where() == nPosCp+1+nCpOfs) 2848 { 2849 WW8_FC nPos; 2850 void *pData; 2851 pTest->Get(nPos, pData); 2852 sal_uInt32 nData = SVBT32ToUInt32(*(SVBT32*)pData); 2853 if (nData & 0x2) //Might be how it works 2854 { 2855 TabCellEnd(); 2856 bRet = false; 2857 } 2858 } 2859 else if (bWasTabCellEnd) 2860 { 2861 TabCellEnd(); 2862 bRet = false; 2863 } 2864 } 2865 2866 bWasTabCellEnd = false; 2867 2868 break; // line end 2869 case 0x5: // Annotation reference 2870 case 0x13: 2871 break; 2872 case 0x2: 2873 if (!maFtnStack.empty()) 2874 cInsert = 0x2; 2875 break; // Auto-Fussnoten-Nummer 2876 #if OSL_DEBUG_LEVEL > 1 2877 default: 2878 ::std::clog << "<unknownValue val=\"" << nWCharVal << "\">" << ::std::endl; 2879 break; 2880 #endif 2881 } 2882 2883 if( '\x0' != cInsert ) 2884 { 2885 String sInsert = ByteString::ConvertToUnicode(cInsert, 2886 RTL_TEXTENCODING_MS_1252 ); 2887 AddTextToParagraph(sInsert); 2888 } 2889 if (!maApos.back()) //a para end in apo doesn't count 2890 bWasParaEnd = bNewParaEnd; 2891 return bRet; 2892 } 2893 2894 void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult& rRes, 2895 bool* pStartAttr, bool bCallProcessSpecial) 2896 { 2897 sal_uInt16 nOldColl = nAktColl; 2898 nAktColl = pPlcxMan->GetColl(); 2899 2900 // Invalid Style-Id 2901 if (nAktColl >= nColls || !pCollA[nAktColl].pFmt || !pCollA[nAktColl].bColl) 2902 { 2903 nAktColl = 0; 2904 bParaAutoBefore = false; 2905 bParaAutoAfter = false; 2906 } 2907 else 2908 { 2909 bParaAutoBefore = pCollA[nAktColl].bParaAutoBefore; 2910 bParaAutoAfter = pCollA[nAktColl].bParaAutoAfter; 2911 } 2912 2913 bool bTabRowEnd = false; 2914 if( pStartAttr && bCallProcessSpecial && !bInHyperlink ) 2915 { 2916 bool bReSync; 2917 // Frame / Table / Autonumbering List Level 2918 bTabRowEnd = ProcessSpecial(bReSync, rRes.nAktCp+pPlcxMan->GetCpOfs()); 2919 if( bReSync ) 2920 *pStartAttr = pPlcxMan->Get( &rRes ); // hole Attribut-Pos neu 2921 } 2922 2923 if (!bTabRowEnd && StyleExists(nAktColl)) 2924 { 2925 SetTxtFmtCollAndListLevel( *pPaM, pCollA[ nAktColl ]); 2926 ChkToggleAttr(pCollA[ nOldColl ].n81Flags, pCollA[ nAktColl ].n81Flags); 2927 ChkToggleBiDiAttr(pCollA[nOldColl].n81BiDiFlags, 2928 pCollA[nAktColl].n81BiDiFlags); 2929 } 2930 } 2931 2932 long SwWW8ImplReader::ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine) 2933 { 2934 long nSkipChars = 0; 2935 WW8PLCFManResult aRes; 2936 2937 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode"); 2938 bool bStartAttr = pPlcxMan->Get(&aRes); // hole Attribut-Pos 2939 aRes.nAktCp = rTxtPos; // Akt. Cp-Pos 2940 2941 bool bNewSection = (aRes.nFlags & MAN_MASK_NEW_SEP) && !bIgnoreText; 2942 if ( bNewSection ) // neue Section 2943 { 2944 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode"); 2945 // PageDesc erzeugen und fuellen 2946 maSectionManager.CreateSep(rTxtPos, bPgSecBreak); 2947 // -> 0xc war ein Sectionbreak, aber 2948 // kein Pagebreak; 2949 bPgSecBreak = false; // PageDesc erzeugen und fuellen 2950 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode"); 2951 } 2952 2953 // neuer Absatz ueber Plcx.Fkp.papx 2954 if ( (aRes.nFlags & MAN_MASK_NEW_PAP)|| rbStartLine ) 2955 { 2956 ProcessAktCollChange( aRes, &bStartAttr, 2957 MAN_MASK_NEW_PAP == (aRes.nFlags & MAN_MASK_NEW_PAP) && 2958 !bIgnoreText ); 2959 rbStartLine = false; 2960 } 2961 2962 // position of last CP that's to be ignored 2963 long nSkipPos = -1; 2964 2965 if( 0 < aRes.nSprmId ) // leere Attrs ignorieren 2966 { 2967 if( ( eFTN > aRes.nSprmId ) || ( 0x0800 <= aRes.nSprmId ) ) 2968 { 2969 if( bStartAttr ) // WW-Attribute 2970 { 2971 if( aRes.nMemLen >= 0 ) 2972 ImportSprm(aRes.pMemPos, aRes.nSprmId); 2973 } 2974 else 2975 EndSprm( aRes.nSprmId ); // Attr ausschalten 2976 } 2977 else if( aRes.nSprmId < 0x800 ) // eigene Hilfs-Attribute 2978 { 2979 if (bStartAttr) 2980 { 2981 nSkipChars = ImportExtSprm(&aRes); 2982 if ( 2983 (aRes.nSprmId == eFTN) || (aRes.nSprmId == eEDN) || 2984 (aRes.nSprmId == eFLD) || (aRes.nSprmId == eAND) 2985 ) 2986 { 2987 // Felder/Ftn-/End-Note hier ueberlesen 2988 rTxtPos += nSkipChars; 2989 nSkipPos = rTxtPos-1; 2990 } 2991 } 2992 else 2993 EndExtSprm( aRes.nSprmId ); 2994 } 2995 } 2996 2997 pStrm->Seek(pSBase->WW8Cp2Fc( pPlcxMan->GetCpOfs() + rTxtPos, &bIsUnicode)); 2998 2999 // Find next Attr position (and Skip attributes of field contents if needed) 3000 if (nSkipChars && !bIgnoreText) 3001 pCtrlStck->MarkAllAttrsOld(); 3002 bool bOldIgnoreText = bIgnoreText; 3003 bIgnoreText = true; 3004 sal_uInt16 nOldColl = nAktColl; 3005 bool bDoPlcxManPlusPLus = true; 3006 long nNext; 3007 do 3008 { 3009 if( bDoPlcxManPlusPLus ) 3010 (*pPlcxMan)++; 3011 nNext = pPlcxMan->Where(); 3012 3013 if (mpPostProcessAttrsInfo && 3014 mpPostProcessAttrsInfo->mnCpStart == nNext) 3015 { 3016 mpPostProcessAttrsInfo->mbCopy = true; 3017 } 3018 3019 if( (0 <= nNext) && (nSkipPos >= nNext) ) 3020 { 3021 nNext = ReadTextAttr( rTxtPos, rbStartLine ); 3022 bDoPlcxManPlusPLus = false; 3023 bIgnoreText = true; 3024 } 3025 3026 if (mpPostProcessAttrsInfo && 3027 nNext > mpPostProcessAttrsInfo->mnCpEnd) 3028 { 3029 mpPostProcessAttrsInfo->mbCopy = false; 3030 } 3031 } 3032 while( nSkipPos >= nNext ); 3033 bIgnoreText = bOldIgnoreText; 3034 if( nSkipChars ) 3035 { 3036 pCtrlStck->KillUnlockedAttrs( *pPaM->GetPoint() ); 3037 if( nOldColl != pPlcxMan->GetColl() ) 3038 ProcessAktCollChange(aRes, 0, false); 3039 } 3040 3041 return nNext; 3042 } 3043 //Modify here for #119405, by easyfan, 2012-05-24 3044 //Revised 2012.8.16 for the complex attribute presentation of 0x0D in MS 3045 bool SwWW8ImplReader::IsParaEndInCPs(sal_Int32 nStart, sal_Int32 nEnd,bool bSdOD) const 3046 { 3047 //Modify for #119405 by chengjh, 2012-08-16 3048 //Revised for performance consideration 3049 if (nStart == -1 || nEnd == -1 || nEnd < nStart ) 3050 return false; 3051 3052 for (cp_vector::const_reverse_iterator aItr = maEndParaPos.rbegin(); aItr!= maEndParaPos.rend(); aItr++) 3053 //End 3054 { 3055 //Revised 2012.8.16,to the 0x0D,the attribute will have two situations 3056 //*********within***********exact******// 3057 //*********but also sample with only left and the position of 0x0d is the edge of the right side***********// 3058 if ( bSdOD && ( (nStart < *aItr && nEnd > *aItr) || ( nStart == nEnd && *aItr == nStart)) ) 3059 return true; 3060 else if ( !bSdOD && (nStart < *aItr && nEnd >= *aItr) ) 3061 return true; 3062 } 3063 3064 return false; 3065 } 3066 //End of modification, by easyfan 3067 //Modify for #119405 by chengjh, 2012-08-16 3068 //Clear the para end position recorded in reader intermittently for the least impact on loading performance 3069 void SwWW8ImplReader::ClearParaEndPosition() 3070 { 3071 if ( maEndParaPos.size() > 0 ) 3072 maEndParaPos.clear(); 3073 } 3074 //End 3075 void SwWW8ImplReader::ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine) 3076 { 3077 if( rTxtPos >= rNext ) 3078 { // Stehen Attribute an ? 3079 3080 do 3081 { 3082 //Modify here for #119405, by easyfan, 2012-05-24 3083 maCurrAttrCP = rTxtPos; 3084 //End of modification, by easyfan 3085 rNext = ReadTextAttr( rTxtPos, rbStartLine ); 3086 } 3087 while( rTxtPos >= rNext ); 3088 3089 } 3090 else if ( rbStartLine ) 3091 { 3092 // keine Attribute, aber trotzdem neue Zeile 3093 // wenn eine Zeile mit einem Seitenumbruch aufhoert und sich keine 3094 // Absatzattribute / Absatzvorlagen aendern, ist das Zeilenende 3095 // nicht im Plcx.Fkp.papx eingetragen, d.h. ( nFlags & MAN_MASK_NEW_PAP ) 3096 // ist false. Deshalb muss als Sonderbehandlung hier die Vorlage gesetzt 3097 // werden. 3098 if (!bCpxStyle && nAktColl < nColls) 3099 SetTxtFmtCollAndListLevel(*pPaM, pCollA[nAktColl]); 3100 rbStartLine = false; 3101 } 3102 } 3103 3104 // CloseAttrEnds zum Lesen nur der Attributenden am Ende eines Textes oder 3105 // Textbereiches ( Kopfzeile, Fussnote, ...). Attributanfaenge, Felder 3106 // werden ignoriert. 3107 void SwWW8ImplReader::CloseAttrEnds() 3108 { 3109 //If there are any unclosed sprms then copy them to 3110 //another stack and close the ones that must be closed 3111 std::stack<sal_uInt16> aStack; 3112 pPlcxMan->TransferOpenSprms(aStack); 3113 3114 while (!aStack.empty()) 3115 { 3116 sal_uInt16 nSprmId = aStack.top(); 3117 if ((0 < nSprmId) && (( eFTN > nSprmId) || (0x0800 <= nSprmId))) 3118 EndSprm(nSprmId); 3119 aStack.pop(); 3120 } 3121 3122 EndSpecial(); 3123 } 3124 3125 bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType) 3126 { 3127 sw::log::Environment eContext = sw::log::eMainText; 3128 if (nType == MAN_MAINTEXT) 3129 eContext = sw::log::eMainText; 3130 else 3131 eContext = sw::log::eSubDoc; 3132 maTracer.EnterEnvironment(eContext); 3133 3134 bool bJoined=false; 3135 3136 bool bStartLine = true; 3137 short nCrCount = 0; 3138 short nDistance = 0; 3139 3140 bWasParaEnd = false; 3141 nAktColl = 0; 3142 pAktItemSet = 0; 3143 nCharFmt = -1; 3144 bSpec = false; 3145 bPgSecBreak = false; 3146 3147 pPlcxMan = new WW8PLCFMan( pSBase, nType, nStartCp ); 3148 long nCpOfs = pPlcxMan->GetCpOfs(); // Offset fuer Header/Footer, Footnote 3149 3150 WW8_CP nNext = pPlcxMan->Where(); 3151 SwTxtNode* pPreviousNode = 0; 3152 sal_uInt8 nDropLines = 0; 3153 SwCharFmt* pNewSwCharFmt = 0; 3154 const SwCharFmt* pFmt = 0; 3155 pStrm->Seek( pSBase->WW8Cp2Fc( nStartCp + nCpOfs, &bIsUnicode ) ); 3156 3157 WW8_CP l = nStartCp; 3158 while ( l<nStartCp+nTextLen ) 3159 { 3160 ReadAttrs( nNext, l, bStartLine );// behandelt auch Section-Breaks 3161 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode"); 3162 3163 if (mpPostProcessAttrsInfo != NULL) 3164 PostProcessAttrs(); 3165 3166 if( l>= nStartCp + nTextLen ) 3167 break; 3168 3169 bStartLine = ReadChars(l, nNext, nStartCp+nTextLen, nCpOfs); 3170 3171 // If the previous paragraph was a dropcap then do not 3172 // create a new txtnode and join the two paragraphs together 3173 3174 if (bStartLine && !pPreviousNode) // Zeilenende 3175 { 3176 bool bSplit = true; 3177 if (mbCareFirstParaEndInToc) 3178 { 3179 mbCareFirstParaEndInToc = false; 3180 if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0) 3181 bSplit = false; 3182 } 3183 if (mbCareLastParaEndInToc) 3184 { 3185 mbCareLastParaEndInToc = false; 3186 if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0) 3187 bSplit = false; 3188 } 3189 if (bSplit) 3190 { 3191 // #119405# - We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream; 3192 if (mbOnLoadingMain) 3193 maEndParaPos.push_back(l-1); 3194 AppendTxtNode(*pPaM->GetPoint()); 3195 } 3196 } 3197 3198 if (pPreviousNode && bStartLine) 3199 { 3200 SwTxtNode* pEndNd = pPaM->GetNode()->GetTxtNode(); 3201 const xub_StrLen nDropCapLen = pPreviousNode->GetTxt().Len(); 3202 3203 // Need to reset the font size and text position for the dropcap 3204 { 3205 SwPaM aTmp(*pEndNd, 0, *pEndNd, nDropCapLen+1); 3206 pCtrlStck->Delete(aTmp); 3207 } 3208 3209 // Get the default document dropcap which we can use as our template 3210 const SwFmtDrop* defaultDrop = 3211 (const SwFmtDrop*) GetFmtAttr(RES_PARATR_DROP); 3212 SwFmtDrop aDrop(*defaultDrop); 3213 3214 aDrop.GetLines() = nDropLines; 3215 aDrop.GetDistance() = nDistance; 3216 aDrop.GetChars() = writer_cast<sal_uInt8>(nDropCapLen); 3217 // Word has no concept of a "whole word dropcap" 3218 aDrop.GetWholeWord() = false; 3219 3220 if (pFmt) 3221 aDrop.SetCharFmt(const_cast<SwCharFmt*>(pFmt)); 3222 else if(pNewSwCharFmt) 3223 aDrop.SetCharFmt(const_cast<SwCharFmt*>(pNewSwCharFmt)); 3224 3225 SwPosition aStart(*pEndNd); 3226 pCtrlStck->NewAttr(aStart, aDrop); 3227 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_DROP); 3228 pPreviousNode = 0; 3229 } 3230 else if (bDropCap) 3231 { 3232 // If we have found a dropcap store the textnode 3233 pPreviousNode = pPaM->GetNode()->GetTxtNode(); 3234 3235 const sal_uInt8 *pDCS; 3236 3237 if (bVer67) 3238 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(46); 3239 else 3240 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C); 3241 3242 if (pDCS) 3243 nDropLines = (*pDCS) >> 3; 3244 else // There is no Drop Cap Specifier hence no dropcap 3245 pPreviousNode = 0; 3246 3247 if (const sal_uInt8 *pDistance = pPlcxMan->GetPapPLCF()->HasSprm(0x842F)) 3248 nDistance = SVBT16ToShort( pDistance ); 3249 else 3250 nDistance = 0; 3251 3252 const SwFmtCharFmt *pSwFmtCharFmt = 0; 3253 3254 if(pAktItemSet) 3255 pSwFmtCharFmt = &(ItemGet<SwFmtCharFmt>(*pAktItemSet, RES_TXTATR_CHARFMT)); 3256 3257 if(pSwFmtCharFmt) 3258 pFmt = pSwFmtCharFmt->GetCharFmt(); 3259 3260 if(pAktItemSet && !pFmt) 3261 { 3262 String sPrefix(CREATE_CONST_ASC( "WW8Dropcap")); 3263 sPrefix += String::CreateFromInt32( nDropCap++ ); 3264 pNewSwCharFmt = rDoc.MakeCharFmt(sPrefix, (SwCharFmt*)rDoc.GetDfltCharFmt()); 3265 pAktItemSet->ClearItem(RES_CHRATR_ESCAPEMENT); 3266 pNewSwCharFmt->SetFmtAttr( *pAktItemSet ); 3267 } 3268 3269 delete pAktItemSet; 3270 pAktItemSet = 0; 3271 bDropCap=false; 3272 } 3273 3274 if (bStartLine || bWasTabRowEnd) 3275 { 3276 // alle 64 CRs aufrufen not for Header u. ae. 3277 if ((nCrCount++ & 0x40) == 0 && nType == MAN_MAINTEXT) 3278 { 3279 nProgress = (sal_uInt16)( l * 100 / nTextLen ); 3280 ::SetProgressState(nProgress, mpDocShell); // Update 3281 } 3282 } 3283 3284 // If we have encountered a 0x0c which indicates either section of 3285 // pagebreak then look it up to see if it is a section break, and 3286 // if it is not then insert a page break. If it is a section break 3287 // it will be handled as such in the ReadAttrs of the next loop 3288 if (bPgSecBreak) 3289 { 3290 // We need only to see if a section is ending at this cp, 3291 // the plcf will already be sitting on the correct location 3292 // if it is there. 3293 WW8PLCFxDesc aTemp; 3294 aTemp.nStartPos = aTemp.nEndPos = WW8_CP_MAX; 3295 if (pPlcxMan->GetSepPLCF()) 3296 pPlcxMan->GetSepPLCF()->GetSprms(&aTemp); 3297 if ((aTemp.nStartPos != l) && (aTemp.nEndPos != l)) 3298 { 3299 // #i39251# - insert text node for page break, if no one inserted. 3300 // #i43118# - refine condition: the anchor control stack has to have entries, 3301 // otherwise it's not needed to insert a text node. 3302 if ( !bStartLine && pAnchorStck->Count() > 0 ) 3303 { 3304 AppendTxtNode(*pPaM->GetPoint()); 3305 } 3306 rDoc.InsertPoolItem(*pPaM, 3307 SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0); 3308 bFirstParaOfPage = true;//xushanchuan add for issue106569 3309 bPgSecBreak = false; 3310 } 3311 } 3312 } 3313 3314 if (pPaM->GetPoint()->nContent.GetIndex()) 3315 AppendTxtNode(*pPaM->GetPoint()); 3316 3317 if (!bInHyperlink) 3318 bJoined = JoinNode(*pPaM); 3319 3320 CloseAttrEnds(); 3321 3322 delete pPlcxMan, pPlcxMan = 0; 3323 maTracer.LeaveEnvironment(eContext); 3324 return bJoined; 3325 } 3326 3327 /*************************************************************************** 3328 # class SwWW8ImplReader 3329 #**************************************************************************/ 3330 3331 SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara, SvStorage* pStorage, 3332 SvStream* pSt, SwDoc& rD, const String& rBaseURL, bool bNewDoc) 3333 : mpDocShell(rD.GetDocShell()) 3334 , maTracer(*(mpDocShell->GetMedium())) 3335 , pStg(pStorage) 3336 , pStrm(pSt) 3337 , pTableStream(0) 3338 , pDataStream(0) 3339 , rDoc(rD) 3340 , maSectionManager(*this) 3341 , maInsertedTables(rD) 3342 , maSectionNameGenerator(rD,CREATE_CONST_ASC("WW")) 3343 , maGrfNameGenerator(bNewDoc,String('G')) 3344 , maParaStyleMapper(rD) 3345 , maCharStyleMapper(rD) 3346 , maTxtNodesHavingFirstLineOfstSet() 3347 , maTxtNodesHavingLeftIndentSet() 3348 , pMSDffManager(0) 3349 , mpAtnNames(0) 3350 , pAuthorInfos(0) 3351 , sBaseURL(rBaseURL) 3352 , m_bRegardHindiDigits( false ) 3353 , mbNewDoc(bNewDoc) 3354 , nDropCap(0) 3355 , nIdctHint(0) 3356 , bBidi(false) 3357 , bReadTable(false) 3358 , mbLoadingTOCCache(false) 3359 , mbLoadingTOCHyperlink(false) 3360 , mpPosAfterTOC(0) 3361 , mbCareFirstParaEndInToc(false) 3362 , mbCareLastParaEndInToc(false) 3363 , maTOXEndCps() 3364 //Modify here for #119405, by easyfan, 2012-05-24 3365 ,maCurrAttrCP(-1), 3366 mbOnLoadingMain(false) 3367 //End of modification, by easyfan 3368 { 3369 pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 3370 nWantedVersion = nVersionPara; 3371 pCtrlStck = 0; 3372 mpRedlineStack = 0; 3373 pReffedStck = 0; 3374 pReffingStck = 0; 3375 pAnchorStck = 0; 3376 pFonts = 0; 3377 pSBase = 0; 3378 pPlcxMan = 0; 3379 pStyles = 0; 3380 pAktColl = 0; 3381 pLstManager = 0; 3382 pAktItemSet = 0; 3383 pCollA = 0; 3384 pDfltTxtFmtColl = 0; 3385 pStandardFmtColl = 0; 3386 pHdFt = 0; 3387 pWFlyPara = 0; 3388 pSFlyPara = 0; 3389 pFlyFmtOfJustInsertedGraphic = 0; 3390 pFmtOfJustInsertedApo = 0; 3391 pPreviousNumPaM = 0; 3392 pPrevNumRule = 0; 3393 nColls = nAktColl = 0; 3394 nObjLocFc = nPicLocFc = 0; 3395 nInTable=0; 3396 bReadNoTbl = bPgSecBreak = bSpec = bObj = bTxbxFlySection 3397 = bHasBorder = bSymbol = bIgnoreText 3398 = bWasTabRowEnd = bWasTabCellEnd = false; 3399 bShdTxtCol = bCharShdTxtCol = bAnl = bHdFtFtnEdn = bFtnEdn 3400 = bIsHeader = bIsFooter = bIsUnicode = bCpxStyle = bStyNormal = 3401 bWWBugNormal = false; 3402 3403 mpPostProcessAttrsInfo = 0; 3404 3405 bNoAttrImport = bPgChpLevel = bEmbeddObj = false; 3406 bAktAND_fNumberAcross = false; 3407 bNoLnNumYet = true; 3408 bInHyperlink = false; 3409 bWasParaEnd = false; 3410 bDropCap = false; 3411 bFirstPara = true; 3412 bFirstParaOfPage = false;//xushanchuan add for issue106569 3413 bParaAutoBefore = false; 3414 bParaAutoAfter = false; 3415 nProgress = 0; 3416 nSwNumLevel = nWwNumType = 0xff; 3417 pTableDesc = 0; 3418 pNumOlst = 0; 3419 pNode_FLY_AT_PARA = 0; 3420 pDrawModel = 0; 3421 pDrawPg = 0; 3422 mpDrawEditEngine = 0; 3423 pWWZOrder = 0; 3424 pFormImpl = 0; 3425 mpChosenOutlineNumRule = 0; 3426 pNumFldType = 0; 3427 nFldNum = 0; 3428 3429 nLFOPosition = USHRT_MAX; 3430 nListLevel = WW8ListManager::nMaxLevel; 3431 eHardCharSet = RTL_TEXTENCODING_DONTKNOW; 3432 3433 nPgChpDelim = nPgChpLevel = 0; 3434 3435 maApos.push_back(false); 3436 } 3437 3438 void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck) 3439 { 3440 if( pStck ) 3441 { 3442 pStck->SetAttr( *pPaM->GetPoint(), 0, false); 3443 pStck->SetAttr( *pPaM->GetPoint(), 0, false); 3444 delete pStck; 3445 } 3446 else 3447 { 3448 ASSERT( !this, "WW-Stack bereits geloescht" ); 3449 } 3450 } 3451 3452 void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection, 3453 bool bTitlePage, bool bIgnoreCols) 3454 { 3455 SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage; 3456 3457 SetNumberingType(rSection, rPage); 3458 3459 SwFrmFmt &rFmt = rPage.GetMaster(); 3460 3461 if(mrReader.pWDop->fUseBackGroundInAllmodes) // #i56806# Make sure mrReader is initialized 3462 mrReader.GrafikCtor(); 3463 3464 3465 if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager) 3466 { 3467 Rectangle aRect(0, 0, 100, 100); //A dummy, we don't care about the size 3468 SvxMSDffImportData aData(aRect); 3469 SdrObject* pObject = 0; 3470 if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData)) 3471 { 3472 SvxMSDffImportRec * pRec = aData.GetRecord(0); 3473 3474 // Only handle shape if it is a background shape 3475 if ((pRec->nFlags & 0x400) != 0) 3476 { 3477 SfxItemSet aSet(rFmt.GetAttrSet()); 3478 mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple, 3479 mso_sptRectangle, aRect); 3480 rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND)); 3481 } 3482 } 3483 } 3484 wwULSpaceData aULData; 3485 GetPageULData(rSection, bTitlePage, aULData); 3486 SetPageULSpaceItems(rFmt, aULData, rSection); 3487 3488 SetPage(rPage, rFmt, rSection, bIgnoreCols); 3489 3490 bool bSetBorder = false; 3491 switch (rSection.maSep.pgbApplyTo) 3492 { 3493 case 0: 3494 case 3: 3495 bSetBorder = true; 3496 break; 3497 case 1: 3498 bSetBorder = bTitlePage; 3499 break; 3500 case 2: 3501 bSetBorder = !bTitlePage; 3502 break; 3503 } 3504 if (bSetBorder) 3505 mrReader.SetPageBorder(rFmt, rSection); 3506 3507 mrReader.SetDocumentGrid(rFmt, rSection); 3508 } 3509 3510 void wwSectionManager::SetUseOn(wwSection &rSection) 3511 { 3512 bool bEven = (rSection.maSep.grpfIhdt & (WW8_HEADER_EVEN|WW8_FOOTER_EVEN)) ? 3513 true : false; 3514 3515 bool bMirror = mrReader.pWDop->fMirrorMargins || 3516 mrReader.pWDop->doptypography.f2on1; 3517 3518 UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL; 3519 UseOnPage eUse = eUseBase; 3520 if (!bEven) 3521 eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE); 3522 3523 ASSERT(rSection.mpPage, "Makes no sense to call me with no pages to set"); 3524 if (rSection.mpPage) 3525 rSection.mpPage->WriteUseOn(eUse); 3526 if (rSection.mpTitlePage) 3527 { 3528 rSection.mpTitlePage->WriteUseOn( 3529 (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE)); 3530 } 3531 3532 if( nsUseOnPage::PD_MIRROR != (UseOnPage)(eUse & nsUseOnPage::PD_MIRROR) ) 3533 { 3534 if( rSection.maSep.bkc == 3 ) 3535 { 3536 if( rSection.mpPage ) 3537 rSection.mpPage->SetUseOn( nsUseOnPage::PD_LEFT ); 3538 if( rSection.mpTitlePage ) 3539 rSection.mpTitlePage->SetUseOn( nsUseOnPage::PD_LEFT ); 3540 } 3541 else if( rSection.maSep.bkc == 4 ) 3542 { 3543 if( rSection.mpPage ) 3544 rSection.mpPage->SetUseOn( nsUseOnPage::PD_RIGHT ); 3545 if( rSection.mpTitlePage ) 3546 rSection.mpTitlePage->SetUseOn( nsUseOnPage::PD_RIGHT ); 3547 } 3548 3549 } 3550 3551 } 3552 3553 //Set the page descriptor on this node, handle the different cases for a text 3554 //node or a table 3555 void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc, 3556 SwDoc &rDoc) 3557 { 3558 /* 3559 If its a table here, apply the pagebreak to the table 3560 properties, otherwise we add it to the para at this 3561 position 3562 */ 3563 if (rIdx.GetNode().IsTableNode()) 3564 { 3565 SwTable& rTable = 3566 rIdx.GetNode().GetTableNode()->GetTable(); 3567 SwFrmFmt* pApply = rTable.GetFrmFmt(); 3568 ASSERT(pApply, "impossible"); 3569 if (pApply) 3570 pApply->SetFmtAttr(rPgDesc); 3571 } 3572 else 3573 { 3574 SwPosition aPamStart(rIdx); 3575 aPamStart.nContent.Assign( 3576 rIdx.GetNode().GetCntntNode(), 0); 3577 SwPaM aPage(aPamStart); 3578 3579 rDoc.InsertPoolItem(aPage, rPgDesc, 0); 3580 } 3581 } 3582 3583 //Map a word section with to either one or two writer page descriptors 3584 //depending on if the word section has a title page 3585 SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter, 3586 mySegIter &rStart, bool bIgnoreCols) 3587 { 3588 SwFmtPageDesc aEmpty; 3589 // Always read title page header/footer data - it could be used by following sections 3590 { 3591 if (IsNewDoc() && rIter == rStart) 3592 { 3593 rIter->mpTitlePage = 3594 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST); 3595 } 3596 else 3597 { 3598 sal_uInt16 nPos = mrReader.rDoc.MakePageDesc( 3599 ViewShell::GetShellRes()->GetPageDescName(mnDesc) 3600 , 0, false); 3601 rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos); 3602 } 3603 ASSERT(rIter->mpTitlePage, "no page!"); 3604 if (!rIter->mpTitlePage) 3605 return aEmpty; 3606 3607 SetSegmentToPageDesc(*rIter, true, bIgnoreCols); 3608 } 3609 3610 if (IsNewDoc() && rIter == rStart) 3611 { 3612 rIter->mpPage = 3613 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD); 3614 } 3615 else 3616 { 3617 sal_uInt16 nPos = mrReader.rDoc.MakePageDesc( 3618 ViewShell::GetShellRes()->GetPageDescName(mnDesc, 3619 false, rIter->HasTitlePage()), 3620 rIter->mpTitlePage, false); 3621 rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos); 3622 } 3623 ASSERT(rIter->mpPage, "no page!"); 3624 if (!rIter->mpPage) 3625 return aEmpty; 3626 3627 //Set page before hd/ft 3628 const wwSection *pPrevious = 0; 3629 3630 mySegIter aPrev = rIter; 3631 while( aPrev!= rStart ) 3632 { 3633 aPrev--; 3634 pPrevious = &(*(aPrev)); 3635 if( aPrev->IsContinous()) 3636 continue; 3637 else{ 3638 break; 3639 } 3640 } 3641 3642 SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious); 3643 SetUseOn(*rIter); 3644 3645 //Set hd/ft after set page 3646 if (rIter->mpTitlePage) 3647 SetSegmentToPageDesc(*rIter, true, bIgnoreCols); 3648 SetSegmentToPageDesc(*rIter, false, bIgnoreCols); 3649 3650 SwFmtPageDesc aRet(rIter->HasTitlePage() ? 3651 rIter->mpTitlePage : rIter->mpPage); 3652 3653 rIter->mpPage->SetFollow(rIter->mpPage); 3654 3655 if (rIter->mpTitlePage) 3656 rIter->mpTitlePage->SetFollow(rIter->mpPage); 3657 3658 if (rIter->PageRestartNo()) 3659 aRet.SetNumOffset(rIter->PageStartAt()); 3660 3661 ++mnDesc; 3662 return aRet; 3663 } 3664 3665 bool wwSectionManager::IsNewDoc() const 3666 { 3667 return mrReader.mbNewDoc; 3668 } 3669 3670 void wwSectionManager::InsertSegments() 3671 { 3672 const SvtFilterOptions* pOpt = SvtFilterOptions::Get(); 3673 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields()); 3674 mySegIter aEnd = maSegments.end(); 3675 mySegIter aStart = maSegments.begin(); 3676 for (mySegIter aIter = aStart; aIter != aEnd; ++aIter) 3677 { 3678 mySegIter aNext = aIter+1; 3679 mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1; 3680 3681 // If two following sections are different in following properties, Word will interprete a continuous 3682 // section break between them as if it was a section break next page. 3683 bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) && 3684 (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape())); 3685 3686 bool bInsertSection = (aIter != aStart) ? (aIter->IsContinous() && bThisAndPreviousAreCompatible): false; 3687 bool bInsertPageDesc = !bInsertSection; 3688 bool bProtected = SectionIsProtected(*aIter); // do we really need this ?? I guess I have a different logic in editshell which disales this... 3689 if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected()) { 3690 // here we have the special case that the whole document is protected, with the execption of this section. 3691 // I want to address this when I do the section rework, so for the moment we disable the overall protection then... 3692 mrReader.rDoc.set(IDocumentSettingAccess::PROTECT_FORM, false ); 3693 } 3694 3695 3696 if (bInsertPageDesc) 3697 { 3698 /* 3699 If a cont section follows this section then we won't be 3700 creating a page desc with 2+ cols as we cannot host a one 3701 col section in a 2+ col pagedesc and make it look like 3702 word. But if the current section actually has columns then 3703 we are forced to insert a section here as well as a page 3704 descriptor. 3705 */ 3706 3707 bool bIgnoreCols = false; 3708 bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) && 3709 (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true; 3710 3711 if (((aNext != aEnd && aNext->IsContinous() && bThisAndNextAreCompatible) || bProtected)) 3712 { 3713 bIgnoreCols = true; 3714 if ((aIter->NoCols() > 1) || bProtected) 3715 bInsertSection = true; 3716 } 3717 3718 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols)); 3719 if (!aDesc.GetPageDesc()) 3720 continue; 3721 GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc); 3722 } 3723 3724 SwTxtNode* pTxtNd = 0; 3725 if (bInsertSection) 3726 { 3727 //Start getting the bounds of this section 3728 SwPaM aSectPaM(*mrReader.pPaM); 3729 SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode); 3730 if (aNext != aEnd) 3731 { 3732 aAnchor = aNext->maStart; 3733 aSectPaM.GetPoint()->nNode = aAnchor; 3734 aSectPaM.GetPoint()->nContent.Assign( 3735 aNext->maStart.GetNode().GetCntntNode(), 0); 3736 aSectPaM.Move(fnMoveBackward); 3737 } 3738 3739 const SwPosition* pPos = aSectPaM.GetPoint(); 3740 SwTxtNode const*const pSttNd = pPos->nNode.GetNode().GetTxtNode(); 3741 const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0; 3742 if (pTableNd) 3743 { 3744 pTxtNd = 3745 mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor, 3746 mrReader.rDoc.GetTxtCollFromPool( RES_POOLCOLL_TEXT )); 3747 3748 aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd); 3749 aSectPaM.GetPoint()->nContent.Assign( 3750 aSectPaM.GetCntntNode(), 0); 3751 } 3752 3753 aSectPaM.SetMark(); 3754 3755 aSectPaM.GetPoint()->nNode = aIter->maStart; 3756 aSectPaM.GetPoint()->nContent.Assign( 3757 aSectPaM.GetCntntNode(), 0); 3758 //End getting the bounds of this section, quite a job eh ? 3759 3760 SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter); 3761 //The last section if continous is always unbalanced 3762 if (pRet) 3763 { 3764 //Set the columns to be UnBalanced if that compatability option 3765 //is set 3766 if (mrReader.pWDop->fNoColumnBalance) 3767 pRet->SetFmtAttr(SwFmtNoBalancedColumns(true)); 3768 else 3769 { 3770 //Otherwise set to unbalanced if the following section is 3771 //not continuous, (which also means that the last section 3772 //is unbalanced) 3773 if (aNext == aEnd || !aNext->IsContinous()) 3774 pRet->SetFmtAttr(SwFmtNoBalancedColumns(true)); 3775 } 3776 } 3777 3778 bool bHasOwnHdFt = false; 3779 /* 3780 In this nightmare scenario the continuous section has its own 3781 headers and footers so we will try and find a hard page break 3782 between here and the end of the section and put the headers and 3783 footers there. 3784 */ 3785 if (!bInsertPageDesc) 3786 { 3787 bHasOwnHdFt = 3788 mrReader.HasOwnHeaderFooter( 3789 aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST), 3790 aIter->maSep.grpfIhdt, std::distance(aStart, aIter) 3791 ); 3792 } 3793 if (bHasOwnHdFt) 3794 { 3795 // #i40766# Need to cache the page descriptor in case there is 3796 // no page break in the section 3797 SwPageDesc *pOrig = aIter->mpPage; 3798 SwPageDesc *pOrigTitle = aIter->mpTitlePage; 3799 bool bFailed = true; 3800 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true)); 3801 if (aDesc.GetPageDesc()) 3802 { 3803 sal_uLong nStart = aSectPaM.Start()->nNode.GetIndex(); 3804 sal_uLong nEnd = aSectPaM.End()->nNode.GetIndex(); 3805 for(; nStart <= nEnd; ++nStart) 3806 { 3807 SwNode* pNode = mrReader.rDoc.GetNodes()[nStart]; 3808 if (!pNode) 3809 continue; 3810 if (sw::util::HasPageBreak(*pNode)) 3811 { 3812 SwNodeIndex aIdx(*pNode); 3813 GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc); 3814 bFailed = false; 3815 break; 3816 } 3817 } 3818 } 3819 if(bFailed) 3820 { 3821 aIter->mpPage = pOrig; 3822 aIter->mpTitlePage = pOrigTitle; 3823 } 3824 } 3825 } 3826 3827 if (pTxtNd) 3828 { 3829 SwNodeIndex aIdx(*pTxtNd); 3830 SwPosition aPos(aIdx); 3831 SwPaM aTest(aPos); 3832 mrReader.rDoc.DelFullPara(aTest); 3833 pTxtNd = 0; 3834 } 3835 } 3836 } 3837 3838 void SwWW8ImplReader::StoreMacroCmds() 3839 { 3840 if (pWwFib->lcbCmds) 3841 { 3842 maTracer.Log(sw::log::eContainsWordBasic); 3843 3844 pTableStream->Seek(pWwFib->fcCmds); 3845 3846 uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage()); 3847 try 3848 { 3849 uno::Reference < io::XStream > xStream = 3850 xRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READWRITE ); 3851 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream ); 3852 3853 sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds]; 3854 pTableStream->Read(pBuffer, pWwFib->lcbCmds); 3855 pStream->Write(pBuffer, pWwFib->lcbCmds); 3856 delete[] pBuffer; 3857 delete pStream; 3858 } 3859 catch ( uno::Exception& ) 3860 { 3861 } 3862 } 3863 } 3864 3865 void SwWW8ImplReader::ReadDocVars() 3866 { 3867 std::vector<String> aDocVarStrings; 3868 std::vector<ww::bytes> aDocVarStringIds; 3869 std::vector<String> aDocValueStrings; 3870 WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser, 3871 pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet, 3872 aDocVarStrings, &aDocVarStringIds, &aDocValueStrings); 3873 if (!bVer67) { 3874 using namespace ::com::sun::star; 3875 3876 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 3877 mpDocShell->GetModel(), uno::UNO_QUERY_THROW); 3878 uno::Reference<document::XDocumentProperties> xDocProps( 3879 xDPS->getDocumentProperties()); 3880 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null"); 3881 uno::Reference<beans::XPropertyContainer> xUserDefinedProps = 3882 xDocProps->getUserDefinedProperties(); 3883 DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null"); 3884 3885 for(size_t i=0; i<aDocVarStrings.size(); i++) 3886 { 3887 uno::Any aDefaultValue; 3888 ::rtl::OUString name(aDocVarStrings[i]); 3889 uno::Any aValue; 3890 aValue <<= ::rtl::OUString(aDocValueStrings[i]); 3891 try { 3892 xUserDefinedProps->addProperty( name, 3893 beans::PropertyAttribute::REMOVEABLE, 3894 aValue ); 3895 } catch (uno::Exception &) { 3896 // ignore 3897 } 3898 } 3899 } 3900 } 3901 3902 //----------------------------------------- 3903 // Document Info 3904 //----------------------------------------- 3905 3906 void SwWW8ImplReader::ReadDocInfo() 3907 { 3908 if( pStg ) 3909 { 3910 uno::Reference<document::XDocumentPropertiesSupplier> xDPS( 3911 mpDocShell->GetModel(), uno::UNO_QUERY_THROW); 3912 uno::Reference<document::XDocumentProperties> xDocProps( 3913 xDPS->getDocumentProperties()); 3914 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null"); 3915 3916 if (xDocProps.is()) { 3917 sfx2::LoadOlePropertySet(xDocProps, pStg); 3918 } 3919 } 3920 } 3921 3922 sal_uLong SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos) 3923 { 3924 sal_uLong nErrRet = 0; 3925 3926 rDoc.SetDocumentType( SwDoc::DOCTYPE_MSWORD ); 3927 if (mbNewDoc && pStg && !pGloss) 3928 ReadDocInfo(); 3929 3930 ::ww8::WW8FibData * pFibData = new ::ww8::WW8FibData(); 3931 3932 if (pWwFib->fReadOnlyRecommended) 3933 pFibData->setReadOnlyRecommended(true); 3934 else 3935 pFibData->setReadOnlyRecommended(false); 3936 3937 if (pWwFib->fWriteReservation) 3938 pFibData->setWriteReservation(true); 3939 else 3940 pFibData->setWriteReservation(false); 3941 3942 ::sw::tExternalDataPointer pExternalFibData(pFibData); 3943 3944 rDoc.setExternalData(::sw::FIB, pExternalFibData); 3945 3946 ::sw::tExternalDataPointer pSttbfAsoc 3947 (new ::ww8::WW8Sttb<ww8::WW8Struct>(*pTableStream, pWwFib->fcSttbfAssoc, pWwFib->lcbSttbfAssoc)); 3948 3949 rDoc.setExternalData(::sw::STTBF_ASSOC, pSttbfAsoc); 3950 3951 if (pWwFib->fWriteReservation || pWwFib->fReadOnlyRecommended) 3952 { 3953 SwDocShell * pDocShell = rDoc.GetDocShell(); 3954 if (pDocShell) 3955 pDocShell->SetReadOnlyUI(sal_True); 3956 } 3957 3958 pPaM = new SwPaM(rPos); 3959 3960 pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this ); 3961 3962 mpRedlineStack = new sw::util::RedlineStack(rDoc); 3963 3964 /* 3965 RefFldStck: Keeps track of bookmarks which may be inserted as 3966 variables intstead. 3967 */ 3968 pReffedStck = new SwFltEndStack(&rDoc, nFieldFlags); 3969 pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags); 3970 3971 pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags); 3972 3973 sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt(); 3974 3975 SwNodeIndex aSttNdIdx( rDoc.GetNodes() ); 3976 SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc); 3977 3978 sal_uInt16 eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT; 3979 3980 mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion()); 3981 3982 // praktische Hilfsvariablen besetzen: 3983 bVer6 = (6 == pWwFib->nVersion); 3984 bVer7 = (7 == pWwFib->nVersion); 3985 bVer67 = bVer6 || bVer7; 3986 bVer8 = (8 == pWwFib->nVersion); 3987 3988 eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse); 3989 eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables); 3990 3991 bWWBugNormal = pWwFib->nProduct == 0xc03d; 3992 3993 if (!mbNewDoc) 3994 aSttNdIdx = pPaM->GetPoint()->nNode; 3995 3996 ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell); 3997 3998 #ifdef DEBUGDUMP 3999 //experimental embedded ttf dumper 4000 if (pWwFib->lcbSttbttmbd && (7 < pWwFib->nVersion)) 4001 { 4002 pTableStream->Seek(pWwFib->fcSttbttmbd); 4003 sal_uInt16 nZeros; 4004 *pTableStream >> nZeros; 4005 sal_uInt16 nNoEntries; 4006 *pTableStream >> nNoEntries; 4007 sal_uInt32 nUnknown1; 4008 *pTableStream >> nUnknown1; 4009 sal_uInt16 nUnknown2; 4010 *pTableStream >> nUnknown2; 4011 std::vector<sal_uInt32> aOffsets; 4012 for (sal_uInt16 nI = 0; nI < nNoEntries; ++nI) 4013 { 4014 sal_uInt32 nOffset; 4015 *pTableStream >> nOffset; 4016 aOffsets.push_back(nOffset); 4017 sal_uInt32 nUnknown3; 4018 *pTableStream >> nUnknown3; 4019 sal_uInt32 nUnknown4; 4020 *pTableStream >> nUnknown4; 4021 } 4022 typedef std::vector<sal_uInt32>::iterator myIter; 4023 myIter aEnd = aOffsets.end(); 4024 myIter aIter = aOffsets.begin(); 4025 while (aIter != aEnd) 4026 { 4027 sal_uInt32 nOffset = *aIter; 4028 sal_uInt32 nLen = STREAM_SEEK_TO_END; 4029 ++aIter; 4030 pStrm->Seek(nOffset); 4031 if (aIter != aEnd) 4032 nLen = *aIter - nOffset; 4033 SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".ttf.dump")); 4034 sw::hack::DumpStream(*pStrm, *pDbg, nLen); 4035 delete pDbg; 4036 } 4037 } 4038 #endif 4039 4040 // read Font Table 4041 pFonts = new WW8Fonts( *pTableStream, *pWwFib ); 4042 4043 // Document Properties 4044 pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop, 4045 pWwFib->lcbDop ); 4046 4047 if (mbNewDoc) 4048 ImportDop(); 4049 4050 /* 4051 Import revisioning data: author names 4052 */ 4053 if( pWwFib->lcbSttbfRMark ) 4054 { 4055 ReadRevMarkAuthorStrTabl( *pTableStream, 4056 pWwFib->fcSttbfRMark, 4057 pWwFib->lcbSttbfRMark, rDoc ); 4058 } 4059 4060 // M.M. Initialize our String/ID map for Linked Sections 4061 std::vector<String> aLinkStrings; 4062 std::vector<ww::bytes> aStringIds; 4063 4064 WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm, 4065 pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet, 4066 aLinkStrings, &aStringIds); 4067 4068 for (size_t i=0; i < aLinkStrings.size(); ++i) 4069 { 4070 ww::bytes stringId = aStringIds[i]; 4071 WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]); 4072 aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] = 4073 aLinkStrings[i]; 4074 } 4075 4076 ReadDocVars(); // import document variables as meta information. 4077 4078 ::SetProgressState(nProgress, mpDocShell); // Update 4079 4080 pLstManager = new WW8ListManager( *pTableStream, *this ); 4081 4082 /* 4083 zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX) 4084 VOR dem Import der Listen !! 4085 */ 4086 ::SetProgressState(nProgress, mpDocShell); // Update 4087 pStyles = new WW8RStyle( *pWwFib, this ); // Styles 4088 pStyles->Import(); 4089 4090 /* 4091 zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX) 4092 =============== 4093 alle Styles durchgehen und ggfs. zugehoeriges Listen-Format 4094 anhaengen NACH dem Import der Styles und NACH dem Import der 4095 Listen !! 4096 */ 4097 ::SetProgressState(nProgress, mpDocShell); // Update 4098 pStyles->PostProcessStyles(); 4099 4100 if (pCollA) 4101 SetOutLineStyles(); 4102 4103 pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib); 4104 4105 static const SvxExtNumType eNumTA[16] = 4106 { 4107 SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER, 4108 SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N, 4109 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC, 4110 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC, 4111 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC, 4112 SVX_NUM_ARABIC, SVX_NUM_ARABIC 4113 }; 4114 4115 if (pSBase->AreThereFootnotes()) 4116 { 4117 static const SwFtnNum eNumA[4] = 4118 { 4119 FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC 4120 }; 4121 4122 SwFtnInfo aInfo; 4123 aInfo = rDoc.GetFtnInfo(); // Copy-Ctor privat 4124 4125 aInfo.ePos = FTNPOS_PAGE; 4126 aInfo.eNum = eNumA[pWDop->rncFtn]; 4127 aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) ); 4128 if( pWDop->nFtn ) 4129 aInfo.nFtnOffset = pWDop->nFtn - 1; 4130 rDoc.SetFtnInfo( aInfo ); 4131 } 4132 if( pSBase->AreThereEndnotes() ) 4133 { 4134 SwEndNoteInfo aInfo; 4135 aInfo = rDoc.GetEndNoteInfo(); // parallel zu Ftn 4136 4137 // Ich kann nicht setzen, wann neu nummerieren... 4138 // aInfo.eNum = eNumA[pWDop->pDop->rncEdn]; 4139 aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) ); 4140 if( pWDop->nEdn ) 4141 aInfo.nFtnOffset = pWDop->nEdn - 1; 4142 rDoc.SetEndNoteInfo( aInfo ); 4143 } 4144 4145 if( pWwFib->lcbPlcfhdd ) 4146 pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop ); 4147 4148 if (!mbNewDoc) 4149 { 4150 // inserting into an existing document: 4151 // As only complete paragraphs are inserted, the current one 4152 // needs to be splitted - once or even twice. 4153 const SwPosition* pPos = pPaM->GetPoint(); 4154 4155 // split current paragraph to get new paragraph for the insertion 4156 rDoc.SplitNode( *pPos, false ); 4157 4158 // another split, if insertion position was not at the end of the current paragraph. 4159 SwTxtNode const*const pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 4160 if ( pTxtNd->GetTxt().Len() ) 4161 { 4162 rDoc.SplitNode( *pPos, false ); 4163 // move PaM back to the newly empty paragraph 4164 pPaM->Move( fnMoveBackward ); 4165 } 4166 4167 // suppress insertion of tables inside footnotes. 4168 const sal_uLong nNd = pPos->nNode.GetIndex(); 4169 bReadNoTbl = ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() && 4170 rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd ); 4171 4172 } 4173 4174 ::SetProgressState(nProgress, mpDocShell); // Update 4175 4176 // loop for each glossary entry and add dummy section node 4177 if (pGloss) 4178 { 4179 WW8PLCF aPlc(pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0); 4180 4181 WW8_CP nStart, nEnd; 4182 void* pDummy; 4183 4184 for (int i=0;i<pGloss->GetNoStrings();i++,aPlc++) 4185 { 4186 SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent()); 4187 SwTxtFmtColl* pColl = 4188 rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD, 4189 false); 4190 SwStartNode *pNode = 4191 rDoc.GetNodes().MakeTextSection(aIdx, 4192 SwNormalStartNode,pColl); 4193 pPaM->GetPoint()->nNode = pNode->GetIndex()+1; 4194 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0); 4195 aPlc.Get( nStart, nEnd, pDummy ); 4196 ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT); 4197 } 4198 } 4199 else //ordinary case 4200 { 4201 //Modify here for #119405, by easyfan, 2012-05-24 4202 mbOnLoadingMain = true; 4203 //End of modification, by easyfan 4204 ReadText(0, pWwFib->ccpText, MAN_MAINTEXT); 4205 //Modify here for #119405, by easyfan, 2012-05-24 4206 mbOnLoadingMain = false; 4207 //End of modification, by easyfan 4208 } 4209 4210 ::SetProgressState(nProgress, mpDocShell); // Update 4211 4212 if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders()) 4213 { 4214 // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten 4215 // Rahmen 4216 SvxMSDffShapeTxBxSort aTxBxSort; 4217 4218 // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen 4219 sal_uInt16 nShapeCount = pMSDffManager->GetShapeOrders()->Count(); 4220 4221 for (sal_uInt16 nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++) 4222 { 4223 SvxMSDffShapeOrder *pOrder = 4224 pMSDffManager->GetShapeOrders()->GetObject(nShapeNum); 4225 // Pointer in neues Sort-Array einfuegen 4226 if (pOrder->nTxBxComp && pOrder->pFly) 4227 aTxBxSort.Insert(pOrder); 4228 } 4229 // zu verkettende Rahmen jetzt verketten 4230 sal_uInt16 nTxBxCount = aTxBxSort.Count(); 4231 if( nTxBxCount ) 4232 { 4233 SwFmtChain aChain; 4234 for (sal_uInt16 nTxBxNum=0; nTxBxNum < nTxBxCount; nTxBxNum++) 4235 { 4236 SvxMSDffShapeOrder *pOrder = 4237 aTxBxSort.GetObject(nTxBxNum); 4238 4239 // Fly-Frame-Formate initialisieren 4240 SwFlyFrmFmt* pFlyFmt = pOrder->pFly; 4241 SwFlyFrmFmt* pNextFlyFmt = 0; 4242 SwFlyFrmFmt* pPrevFlyFmt = 0; 4243 // ggfs. Nachfolger ermitteln 4244 if( 1+nTxBxNum < nTxBxCount ) 4245 { 4246 SvxMSDffShapeOrder *pNextOrder = 4247 aTxBxSort.GetObject(nTxBxNum+1); 4248 if ((0xFFFF0000 & pOrder->nTxBxComp) 4249 == (0xFFFF0000 & pNextOrder->nTxBxComp)) 4250 pNextFlyFmt = pNextOrder->pFly; 4251 } 4252 // ggfs. Vorgaenger ermitteln 4253 if( nTxBxNum ) 4254 { 4255 SvxMSDffShapeOrder *pPrevOrder = 4256 aTxBxSort.GetObject(nTxBxNum-1); 4257 if ((0xFFFF0000 & pOrder->nTxBxComp) 4258 == (0xFFFF0000 & pPrevOrder->nTxBxComp)) 4259 pPrevFlyFmt = pPrevOrder->pFly; 4260 } 4261 // Falls Nachfolger oder Vorgaenger vorhanden, 4262 // die Verkettung am Fly-Frame-Format eintragen 4263 if (pNextFlyFmt || pPrevFlyFmt) 4264 { 4265 aChain.SetNext( pNextFlyFmt ); 4266 aChain.SetPrev( pPrevFlyFmt ); 4267 pFlyFmt->SetFmtAttr( aChain ); 4268 } 4269 } 4270 4271 } 4272 4273 } 4274 4275 if (mbNewDoc) 4276 { 4277 if( pWDop->fRevMarking ) 4278 eMode |= nsRedlineMode_t::REDLINE_ON; 4279 if( pWDop->fRMView ) 4280 eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE; 4281 if (pStg && !pGloss) /*meaningless for a glossary, cmc*/ 4282 { 4283 const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get(); 4284 maTracer.EnterEnvironment(sw::log::eMacros); 4285 SvxImportMSVBasic aVBasic(*mpDocShell, *pStg, 4286 pVBAFlags->IsLoadWordBasicCode(), 4287 pVBAFlags->IsLoadWordBasicStorage() ); 4288 String s1(CREATE_CONST_ASC("Macros")); 4289 String s2(CREATE_CONST_ASC("VBA")); 4290 int nRet = aVBasic.Import( s1, s2 ); 4291 if( 2 & nRet ) 4292 { 4293 maTracer.Log(sw::log::eContainsVisualBasic); 4294 rDoc.SetContainsMSVBasic(true); 4295 } 4296 4297 StoreMacroCmds(); 4298 4299 maTracer.LeaveEnvironment(sw::log::eMacros); 4300 } 4301 } 4302 4303 maInsertedTables.DelAndMakeTblFrms(); 4304 maSectionManager.InsertSegments(); 4305 4306 if (pCollA) 4307 delete[] pCollA; 4308 4309 DELETEZ( pStyles ); 4310 4311 if( pFormImpl ) 4312 DeleteFormImpl(); 4313 GrafikDtor(); 4314 DELETEZ( pMSDffManager ); 4315 DELETEZ( pHdFt ); 4316 DELETEZ( pLstManager ); 4317 DELETEZ( pSBase ); 4318 delete pWDop; 4319 DELETEZ( pFonts ); 4320 delete mpAtnNames; 4321 DELETEZ( pAuthorInfos ); 4322 delete mpSprmParser; 4323 ::EndProgress(mpDocShell); 4324 4325 pDataStream = 0; 4326 pTableStream = 0; 4327 4328 DeleteCtrlStk(); 4329 mpRedlineStack->closeall(*pPaM->GetPoint()); 4330 delete mpRedlineStack; 4331 DeleteAnchorStk(); 4332 DeleteRefStks(); 4333 4334 UpdateFields(); 4335 4336 // delete the pam before the call for hide all redlines (Bug 73683) 4337 if (mbNewDoc) 4338 rDoc.SetRedlineMode((RedlineMode_t)( eMode )); 4339 4340 UpdatePageDescs(rDoc, nPageDescOffset); 4341 4342 delete pPaM, pPaM = 0; 4343 return nErrRet; 4344 } 4345 4346 sal_uLong SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream, 4347 SvStorageStreamRef &rDataStream) 4348 { 4349 sal_uLong nErrRet = 0; 4350 // 6 stands for "6 OR 7", 7 stand for "ONLY 7" 4351 switch (pWwFib->nVersion) 4352 { 4353 case 6: 4354 case 7: 4355 pTableStream = pStrm; 4356 pDataStream = pStrm; 4357 break; 4358 case 8: 4359 if(!pStg) 4360 { 4361 ASSERT( pStg, "Version 8 muss immer einen Storage haben!" ); 4362 nErrRet = ERR_SWG_READ_ERROR; 4363 break; 4364 } 4365 4366 rTableStream = pStg->OpenSotStream( String::CreateFromAscii( 4367 pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table), 4368 STREAM_STD_READ); 4369 4370 pTableStream = &rTableStream; 4371 pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN ); 4372 4373 rDataStream = pStg->OpenSotStream(CREATE_CONST_ASC(SL::aData), 4374 STREAM_STD_READ | STREAM_NOCREATE ); 4375 4376 if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError()) 4377 { 4378 pDataStream = &rDataStream; 4379 pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); 4380 } 4381 else 4382 pDataStream = pStrm; 4383 break; 4384 default: 4385 // Programm-Fehler! 4386 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" ); 4387 nErrRet = ERR_SWG_READ_ERROR; 4388 break; 4389 } 4390 return nErrRet; 4391 } 4392 4393 namespace 4394 { 4395 utl::TempFile *MakeTemp(SvFileStream &rSt) 4396 { 4397 utl::TempFile *pT = new utl::TempFile; 4398 pT->EnableKillingFile(); 4399 rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE); 4400 return pT; 4401 } 4402 4403 #define WW_BLOCKSIZE 0x200 4404 4405 void DecryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut) 4406 { 4407 rIn.Seek(STREAM_SEEK_TO_END); 4408 sal_uLong nLen = rIn.Tell(); 4409 rIn.Seek(0); 4410 4411 sal_uInt8 in[WW_BLOCKSIZE]; 4412 for (sal_uLong nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock) 4413 { 4414 sal_uLong nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI; 4415 rIn.Read(in, nBS); 4416 rCtx.InitCipher(nBlock); 4417 rCtx.Decode(in, nBS, in, nBS); 4418 rOut.Write(in, nBS); 4419 } 4420 } 4421 4422 void DecryptXOR(msfilter::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut) 4423 { 4424 sal_uLong nSt = rIn.Tell(); 4425 rIn.Seek(STREAM_SEEK_TO_END); 4426 sal_uLong nLen = rIn.Tell(); 4427 rIn.Seek(nSt); 4428 4429 rCtx.InitCipher(); 4430 rCtx.Skip(nSt); 4431 4432 sal_uInt8 in[0x4096]; 4433 for (sal_uLong nI = nSt; nI < nLen; nI += 0x4096) 4434 { 4435 sal_uLong nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI; 4436 rIn.Read(in, nBS); 4437 rCtx.Decode(in, nBS); 4438 rOut.Write(in, nBS); 4439 } 4440 } 4441 4442 //moan, copy and paste :-( 4443 String QueryPasswordForMedium(SfxMedium& rMedium) 4444 { 4445 String aPassw; 4446 4447 using namespace com::sun::star; 4448 4449 const SfxItemSet* pSet = rMedium.GetItemSet(); 4450 const SfxPoolItem *pPasswordItem; 4451 4452 if(pSet && SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, sal_True, &pPasswordItem)) 4453 aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue(); 4454 else 4455 { 4456 try 4457 { 4458 uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() ); 4459 if( xHandler.is() ) 4460 { 4461 ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest( 4462 ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER, 4463 INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) ); 4464 uno::Reference< task::XInteractionRequest > xRequest( pRequest ); 4465 4466 xHandler->handle( xRequest ); 4467 4468 if( pRequest->isPassword() ) 4469 aPassw = pRequest->getPassword(); 4470 } 4471 } 4472 catch( uno::Exception& ) 4473 { 4474 } 4475 } 4476 4477 return aPassw; 4478 } 4479 4480 uno::Sequence< beans::NamedValue > InitXorWord95Codec( ::msfilter::MSCodec_XorWord95& rCodec, SfxMedium& rMedium, WW8Fib* pWwFib ) 4481 { 4482 uno::Sequence< beans::NamedValue > aEncryptionData; 4483 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False ); 4484 if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) ) 4485 aEncryptionData.realloc( 0 ); 4486 4487 if ( !aEncryptionData.getLength() ) 4488 { 4489 String sUniPassword = QueryPasswordForMedium( rMedium ); 4490 4491 ByteString sPassword(sUniPassword, WW8Fib::GetFIBCharset( pWwFib->chseTables ) ); 4492 4493 xub_StrLen nLen = sPassword.Len(); 4494 if( nLen <= 15 ) 4495 { 4496 sal_uInt8 pPassword[16]; 4497 memset( pPassword, 0, sizeof( pPassword ) ); 4498 4499 for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar ) 4500 pPassword[nChar] = sPassword.GetChar(nChar); 4501 4502 rCodec.InitKey( pPassword ); 4503 aEncryptionData = rCodec.GetEncryptionData(); 4504 4505 // the export supports RC4 algorithm only, so we have to generate the related EncryptionData as well, 4506 // so that Save can export the document without asking for a password; 4507 // as result there will be EncryptionData for both algorithms in the MediaDescriptor 4508 ::msfilter::MSCodec_Std97 aCodec97; 4509 4510 // Generate random number with a seed of time as salt. 4511 TimeValue aTime; 4512 osl_getSystemTime( &aTime ); 4513 rtlRandomPool aRandomPool = rtl_random_createPool(); 4514 rtl_random_addBytes ( aRandomPool, &aTime, 8 ); 4515 4516 sal_uInt8 pDocId[ 16 ]; 4517 rtl_random_getBytes( aRandomPool, pDocId, 16 ); 4518 4519 rtl_random_destroyPool( aRandomPool ); 4520 4521 sal_uInt16 pStd97Pass[16]; 4522 memset( pStd97Pass, 0, sizeof( pStd97Pass ) ); 4523 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar ) 4524 pStd97Pass[nChar] = sUniPassword.GetChar(nChar); 4525 4526 aCodec97.InitKey( pStd97Pass, pDocId ); 4527 4528 // merge the EncryptionData, there should be no conflicts 4529 ::comphelper::SequenceAsHashMap aEncryptionHash( aEncryptionData ); 4530 aEncryptionHash.update( ::comphelper::SequenceAsHashMap( aCodec97.GetEncryptionData() ) ); 4531 aEncryptionHash >> aEncryptionData; 4532 } 4533 } 4534 4535 return aEncryptionData; 4536 } 4537 4538 uno::Sequence< beans::NamedValue > InitStd97Codec( ::msfilter::MSCodec_Std97& rCodec, sal_uInt8 pDocId[16], SfxMedium& rMedium ) 4539 { 4540 uno::Sequence< beans::NamedValue > aEncryptionData; 4541 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False ); 4542 if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) ) 4543 aEncryptionData.realloc( 0 ); 4544 4545 if ( !aEncryptionData.getLength() ) 4546 { 4547 String sUniPassword = QueryPasswordForMedium( rMedium ); 4548 4549 xub_StrLen nLen = sUniPassword.Len(); 4550 if ( nLen <= 15 ) 4551 { 4552 sal_Unicode pPassword[16]; 4553 memset( pPassword, 0, sizeof( pPassword ) ); 4554 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar ) 4555 pPassword[nChar] = sUniPassword.GetChar(nChar); 4556 4557 rCodec.InitKey( pPassword, pDocId ); 4558 aEncryptionData = rCodec.GetEncryptionData(); 4559 } 4560 } 4561 4562 return aEncryptionData; 4563 } 4564 } 4565 4566 sal_uLong SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss) 4567 { 4568 sal_uLong nErrRet = 0; 4569 if (pGloss) 4570 pWwFib = pGloss->GetFib(); 4571 else 4572 pWwFib = new WW8Fib(*pStrm, nWantedVersion); 4573 4574 if (pWwFib->nFibError) 4575 nErrRet = ERR_SWG_READ_ERROR; 4576 4577 SvStorageStreamRef xTableStream, xDataStream; 4578 4579 if (!nErrRet) 4580 nErrRet = SetSubStreams(xTableStream, xDataStream); 4581 4582 utl::TempFile *pTempMain = 0; 4583 utl::TempFile *pTempTable = 0; 4584 utl::TempFile *pTempData = 0; 4585 SvFileStream aDecryptMain; 4586 SvFileStream aDecryptTable; 4587 SvFileStream aDecryptData; 4588 4589 bool bDecrypt = false; 4590 enum {RC4, XOR, Other} eAlgo = Other; 4591 if (pWwFib->fEncrypted && !nErrRet) 4592 { 4593 if (!pGloss) 4594 { 4595 bDecrypt = true; 4596 if (8 != pWwFib->nVersion) 4597 eAlgo = XOR; 4598 else 4599 { 4600 if (pWwFib->nKey != 0) 4601 eAlgo = XOR; 4602 else 4603 { 4604 pTableStream->Seek(0); 4605 sal_uInt32 nEncType; 4606 *pTableStream >> nEncType; 4607 if (nEncType == 0x10001) 4608 eAlgo = RC4; 4609 } 4610 } 4611 } 4612 } 4613 4614 if (bDecrypt) 4615 { 4616 nErrRet = ERRCODE_SVX_WRONGPASS; 4617 SfxMedium* pMedium = mpDocShell->GetMedium(); 4618 4619 if ( pMedium ) 4620 { 4621 switch (eAlgo) 4622 { 4623 default: 4624 nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT; 4625 break; 4626 case XOR: 4627 { 4628 msfilter::MSCodec_XorWord95 aCtx; 4629 uno::Sequence< beans::NamedValue > aEncryptionData = InitXorWord95Codec( aCtx, *pMedium, pWwFib ); 4630 4631 // if initialization has failed the EncryptionData should be empty 4632 if ( aEncryptionData.getLength() && aCtx.VerifyKey( pWwFib->nKey, pWwFib->nHash ) ) 4633 { 4634 nErrRet = 0; 4635 pTempMain = MakeTemp(aDecryptMain); 4636 4637 pStrm->Seek(0); 4638 size_t nUnencryptedHdr = 4639 (8 == pWwFib->nVersion) ? 0x44 : 0x34; 4640 sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr]; 4641 pStrm->Read(pIn, nUnencryptedHdr); 4642 aDecryptMain.Write(pIn, nUnencryptedHdr); 4643 delete [] pIn; 4644 4645 DecryptXOR(aCtx, *pStrm, aDecryptMain); 4646 4647 if (!pTableStream || pTableStream == pStrm) 4648 pTableStream = &aDecryptMain; 4649 else 4650 { 4651 pTempTable = MakeTemp(aDecryptTable); 4652 DecryptXOR(aCtx, *pTableStream, aDecryptTable); 4653 pTableStream = &aDecryptTable; 4654 } 4655 4656 if (!pDataStream || pDataStream == pStrm) 4657 pDataStream = &aDecryptMain; 4658 else 4659 { 4660 pTempData = MakeTemp(aDecryptData); 4661 DecryptXOR(aCtx, *pDataStream, aDecryptData); 4662 pDataStream = &aDecryptData; 4663 } 4664 4665 pMedium->GetItemSet()->ClearItem( SID_PASSWORD ); 4666 pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) ); 4667 } 4668 } 4669 break; 4670 case RC4: 4671 { 4672 msfilter::MSCodec_Std97 aCtx; 4673 4674 sal_uInt8 aDocId[ 16 ]; 4675 pTableStream->Read(aDocId, 16); 4676 sal_uInt8 aSaltData[ 16 ]; 4677 pTableStream->Read(aSaltData, 16); 4678 sal_uInt8 aSaltHash[ 16 ]; 4679 pTableStream->Read(aSaltHash, 16); 4680 4681 // if initialization has failed the EncryptionData should be empty 4682 uno::Sequence< beans::NamedValue > aEncryptionData = InitStd97Codec( aCtx, aDocId, *pMedium ); 4683 if ( aEncryptionData.getLength() && aCtx.VerifyKey( aSaltData, aSaltHash ) ) 4684 { 4685 nErrRet = 0; 4686 4687 pTempTable = MakeTemp(aDecryptTable); 4688 DecryptRC4(aCtx, *pTableStream, aDecryptTable); 4689 pTableStream = &aDecryptTable; 4690 4691 pTempMain = MakeTemp(aDecryptMain); 4692 DecryptRC4(aCtx, *pStrm, aDecryptMain); 4693 4694 if (!pDataStream || pDataStream == pStrm) 4695 pDataStream = &aDecryptMain; 4696 else 4697 { 4698 pTempData = MakeTemp(aDecryptData); 4699 DecryptRC4(aCtx, *pDataStream, aDecryptData); 4700 pDataStream = &aDecryptData; 4701 } 4702 4703 pMedium->GetItemSet()->ClearItem( SID_PASSWORD ); 4704 pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) ); 4705 } 4706 } 4707 break; 4708 } 4709 } 4710 4711 if (nErrRet == 0) 4712 { 4713 pStrm = &aDecryptMain; 4714 4715 delete pWwFib; 4716 pWwFib = new WW8Fib(*pStrm, nWantedVersion); 4717 if (pWwFib->nFibError) 4718 nErrRet = ERR_SWG_READ_ERROR; 4719 } 4720 } 4721 4722 if (!nErrRet) 4723 nErrRet = CoreLoad(pGloss, *rPaM.GetPoint()); 4724 4725 delete pTempMain; 4726 delete pTempTable; 4727 delete pTempData; 4728 4729 if (!pGloss) 4730 delete pWwFib; 4731 return nErrRet; 4732 } 4733 4734 class outlineeq : public std::unary_function<const SwTxtFmtColl*, bool> 4735 { 4736 private: 4737 sal_uInt8 mnNum; 4738 public: 4739 outlineeq(sal_uInt8 nNum) : mnNum(nNum) {} 4740 bool operator()(const SwTxtFmtColl *pTest) const 4741 { 4742 //return pTest->GetOutlineLevel() == mnNum; //#outline level,zhaojianwei 4743 return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum; //<-end,zhaojianwei 4744 } 4745 }; 4746 4747 void SwWW8ImplReader::SetOutLineStyles() 4748 { 4749 /* 4750 #i3674# - Load new document and insert document cases. 4751 */ 4752 SwNumRule aOutlineRule(*rDoc.GetOutlineNumRule()); 4753 // #i53044,i53213# 4754 // <mpChosenOutlineNumRule> has to be set to point to local variable 4755 // <aOutlineRule>, because its used below to be compared this <&aOutlineRule>. 4756 // But at the end of the method <mpChosenOutlineNumRule> has to be set to 4757 // <rDoc.GetOutlineNumRule()>, because <aOutlineRule> will be destroyed. 4758 mpChosenOutlineNumRule = &aOutlineRule; 4759 4760 sw::ParaStyles aOutLined(sw::util::GetParaStyles(rDoc)); 4761 // #i98791# - sorting algorithm adjusted 4762 sw::util::SortByAssignedOutlineStyleListLevel(aOutLined); 4763 4764 typedef sw::ParaStyleIter myParaStyleIter; 4765 /* 4766 If we are inserted into a document then don't clobber existing existing 4767 levels. 4768 */ 4769 sal_uInt16 nFlagsStyleOutlLevel = 0; 4770 if (!mbNewDoc) 4771 { 4772 // #i70748# - backward iteration needed due to the outline level attribute 4773 sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend(); 4774 for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter) 4775 { 4776 if ((*aIter)->IsAssignedToListLevelOfOutlineStyle()) 4777 nFlagsStyleOutlLevel |= 1 << (*aIter)->GetAssignedOutlineStyleLevel(); 4778 else 4779 break; 4780 } 4781 } 4782 else 4783 { 4784 /* 4785 Only import *one* of the possible multiple outline numbering rules, so 4786 pick the one that affects most styles. If we're not importing a new 4787 document, we got to stick with what is already there. 4788 */ 4789 // use index in text format collection 4790 // array <pCollA> as key of the outline numbering map <aRuleMap> 4791 // instead of the memory pointer of the outline numbering rule 4792 // to assure that, if two outline numbering rule affect the same 4793 // count of text formats, always the same outline numbering rule is chosen. 4794 std::map<sal_uInt16, int>aRuleMap; 4795 typedef std::map<sal_uInt16, int>::iterator myIter; 4796 for (sal_uInt16 nI = 0; nI < nColls; ++nI) 4797 { 4798 SwWW8StyInf& rSI = pCollA[ nI ]; 4799 if ( 4800 (MAXLEVEL > rSI.nOutlineLevel) && rSI.pOutlineNumrule && 4801 rSI.pFmt 4802 ) 4803 { 4804 myIter aIter = aRuleMap.find(nI); 4805 if (aIter == aRuleMap.end()) 4806 { 4807 aRuleMap[nI] = 1; 4808 } 4809 else 4810 ++(aIter->second); 4811 } 4812 } 4813 4814 int nMax = 0; 4815 myIter aEnd2 = aRuleMap.end(); 4816 for (myIter aIter = aRuleMap.begin(); aIter != aEnd2; ++aIter++) 4817 { 4818 if (aIter->second > nMax) 4819 { 4820 nMax = aIter->second; 4821 mpChosenOutlineNumRule = pCollA[ aIter->first ].pOutlineNumrule; 4822 } 4823 } 4824 4825 ASSERT(mpChosenOutlineNumRule, "Impossible"); 4826 if (mpChosenOutlineNumRule) 4827 aOutlineRule = *mpChosenOutlineNumRule; 4828 4829 if (mpChosenOutlineNumRule != &aOutlineRule) 4830 { 4831 // #i70748# - backward iteration needed due to the outline level attribute 4832 sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend(); 4833 for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter) 4834 { 4835 if((*aIter)->IsAssignedToListLevelOfOutlineStyle()) 4836 (*aIter)->DeleteAssignmentToListLevelOfOutlineStyle(); 4837 4838 else 4839 break; 4840 } 4841 } 4842 } 4843 4844 sal_uInt16 nOldFlags = nFlagsStyleOutlLevel; 4845 4846 for (sal_uInt16 nI = 0; nI < nColls; ++nI) 4847 { 4848 SwWW8StyInf& rSI = pCollA[nI]; 4849 4850 if (rSI.IsOutlineNumbered()) 4851 { 4852 sal_uInt16 nAktFlags = 1 << rSI.nOutlineLevel; 4853 if ( 4854 (nAktFlags & nFlagsStyleOutlLevel) || 4855 (rSI.pOutlineNumrule != mpChosenOutlineNumRule) 4856 ) 4857 { 4858 /* 4859 If our spot is already taken by something we can't replace 4860 then don't insert and remove our outline level. 4861 */ 4862 rSI.pFmt->SetFmtAttr( 4863 SwNumRuleItem( rSI.pOutlineNumrule->GetName() ) ); 4864 //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(NO_NUMBERING); 4865 ((SwTxtFmtColl*)rSI.pFmt)->DeleteAssignmentToListLevelOfOutlineStyle();//#outline level,zhaojianwei 4866 } 4867 else 4868 { 4869 /* 4870 If there is a style already set for this outline 4871 numbering level and its not a style set by us already 4872 then we can remove it outline numbering. 4873 (its one of the default headings in a new document 4874 so we can clobber it) 4875 Of course if we are being inserted into a document that 4876 already has some set we can't do this, thats covered by 4877 the list of level in nFlagsStyleOutlLevel to ignore. 4878 */ 4879 outlineeq aCmp(rSI.nOutlineLevel); 4880 myParaStyleIter aResult = std::find_if(aOutLined.begin(), 4881 aOutLined.end(), aCmp); 4882 4883 myParaStyleIter aEnd = aOutLined.end(); 4884 while (aResult != aEnd && aCmp(*aResult)) 4885 { 4886 //(*aResult)->SetOutlineLevel(NO_NUMBERING);//#outline level,zhaojianwei 4887 (*aResult)->DeleteAssignmentToListLevelOfOutlineStyle(); 4888 ++aResult; 4889 } 4890 4891 /* 4892 #i1886# 4893 I believe that when a list is registered onto a winword 4894 style which is an outline numbering style (i.e. 4895 nOutlineLevel is set) that the style of numbering is for 4896 the level is indexed by the *list* level that was 4897 registered on that style, and not the outlinenumbering 4898 level, which is probably a logical sequencing, and not a 4899 physical mapping into the list style reged on that outline 4900 style. 4901 */ 4902 sal_uInt8 nFromLevel = rSI.nListLevel; 4903 sal_uInt8 nToLevel = rSI.nOutlineLevel; 4904 const SwNumFmt& rRule=rSI.pOutlineNumrule->Get(nFromLevel); 4905 aOutlineRule.Set(nToLevel, rRule); 4906 // Set my outline level 4907 //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(nToLevel);//#outline level,zhaojianwei 4908 ((SwTxtFmtColl*)rSI.pFmt)->AssignToListLevelOfOutlineStyle(nToLevel); //<-end,zhaojianwei 4909 // If there are more styles on this level ignore them 4910 nFlagsStyleOutlLevel |= nAktFlags; 4911 } 4912 } 4913 } 4914 if (nOldFlags != nFlagsStyleOutlLevel) 4915 rDoc.SetOutlineNumRule(aOutlineRule); 4916 if ( mpChosenOutlineNumRule == &aOutlineRule ) 4917 { 4918 mpChosenOutlineNumRule = rDoc.GetOutlineNumRule(); 4919 } 4920 } 4921 4922 const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx) 4923 { 4924 if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners) 4925 { 4926 // Authoren bestimmen: steht im TableStream 4927 mpAtnNames = new ::std::vector<String>; 4928 SvStream& rStrm = *pTableStream; 4929 4930 long nOldPos = rStrm.Tell(); 4931 rStrm.Seek( pWwFib->fcGrpStAtnOwners ); 4932 4933 long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners; 4934 while (nRead < nCount) 4935 { 4936 if( bVer67 ) 4937 { 4938 mpAtnNames->push_back(WW8ReadPString(rStrm, false)); 4939 nRead += mpAtnNames->rbegin()->Len() + 1; // Laenge + sal_uInt8 Count 4940 } 4941 else 4942 { 4943 mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false)); 4944 // UNICode: doppelte Laenge + sal_uInt16 Count 4945 nRead += mpAtnNames->rbegin()->Len() * 2 + 2; 4946 } 4947 } 4948 rStrm.Seek( nOldPos ); 4949 } 4950 4951 const String *pRet = 0; 4952 if (mpAtnNames && nIdx < mpAtnNames->size()) 4953 pRet = &((*mpAtnNames)[nIdx]); 4954 return pRet; 4955 } 4956 4957 sal_uLong SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss) 4958 { 4959 sal_uLong nErrRet = 0; 4960 4961 { 4962 static const sal_Char* aNames[ 13 ] = { 4963 "WinWord/WW", "WinWord/WW8", "WinWord/WWFT", 4964 "WinWord/WWFLX", "WinWord/WWFLY", 4965 "WinWord/WWF", 4966 "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2", 4967 "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2", 4968 "WinWord/RegardHindiDigits" 4969 }; 4970 sal_uInt32 aVal[ 13 ]; 4971 4972 SwFilterOptions aOpt( 13, aNames, aVal ); 4973 4974 nIniFlags = aVal[ 0 ]; 4975 nIniFlags1= aVal[ 1 ]; 4976 // schiebt Flys um x twips nach rechts o. links 4977 nIniFlyDx = aVal[ 3 ]; 4978 nIniFlyDy = aVal[ 4 ]; 4979 4980 nFieldFlags = aVal[ 5 ]; 4981 nFieldTagAlways[0] = aVal[ 6 ]; 4982 nFieldTagAlways[1] = aVal[ 7 ]; 4983 nFieldTagAlways[2] = aVal[ 8 ]; 4984 nFieldTagBad[0] = aVal[ 9 ]; 4985 nFieldTagBad[1] = aVal[ 10 ]; 4986 nFieldTagBad[2] = aVal[ 11 ]; 4987 m_bRegardHindiDigits = aVal[ 12 ] > 0; 4988 } 4989 4990 sal_uInt16 nMagic; 4991 *pStrm >> nMagic; 4992 4993 // beachte: 6 steht fuer "6 ODER 7", 7 steht fuer "NUR 7" 4994 switch (nWantedVersion) 4995 { 4996 case 6: 4997 case 7: 4998 if ( 4999 (0xa5dc != nMagic && 0xa5db != nMagic) && 5000 (nMagic < 0xa697 || nMagic > 0xa699) 5001 ) 5002 { 5003 //JP 06.05.99: teste auf eigenen 97-Fake! 5004 if (pStg && 0xa5ec == nMagic) 5005 { 5006 sal_uLong nCurPos = pStrm->Tell(); 5007 if (pStrm->Seek(nCurPos + 22)) 5008 { 5009 sal_uInt32 nfcMin; 5010 *pStrm >> nfcMin; 5011 if (0x300 != nfcMin) 5012 nErrRet = ERR_WW6_NO_WW6_FILE_ERR; 5013 } 5014 pStrm->Seek( nCurPos ); 5015 } 5016 else 5017 nErrRet = ERR_WW6_NO_WW6_FILE_ERR; 5018 } 5019 break; 5020 case 8: 5021 if (0xa5ec != nMagic) 5022 nErrRet = ERR_WW8_NO_WW8_FILE_ERR; 5023 break; 5024 default: 5025 nErrRet = ERR_WW8_NO_WW8_FILE_ERR; 5026 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" ); 5027 break; 5028 } 5029 5030 if (!nErrRet) 5031 nErrRet = LoadThroughDecryption(rPaM ,pGloss); 5032 5033 rDoc.PropagateOutlineRule(); 5034 5035 return nErrRet; 5036 } 5037 5038 extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC() 5039 { 5040 return new WW8Reader(); 5041 } 5042 5043 sal_uLong WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */) 5044 { 5045 sal_uInt16 nOldBuffSize = 32768; 5046 bool bNew = !bInsertMode; // Neues Doc ( kein Einfuegen ) 5047 5048 5049 SvStorageStreamRef refStrm; // damit uns keiner den Stream klaut 5050 SvStream* pIn = pStrm; 5051 5052 sal_uLong nRet = 0; 5053 sal_uInt8 nVersion = 8; 5054 5055 String sFltName = GetFltName(); 5056 if( sFltName.EqualsAscii( "WW6" ) ) 5057 { 5058 if (pStrm) 5059 nVersion = 6; 5060 else 5061 { 5062 ASSERT(!this, "WinWord 95 Reader-Read ohne Stream"); 5063 nRet = ERR_SWG_READ_ERROR; 5064 } 5065 } 5066 else 5067 { 5068 if( sFltName.EqualsAscii( "CWW6" ) ) 5069 nVersion = 6; 5070 else if( sFltName.EqualsAscii( "CWW7" ) ) 5071 nVersion = 7; 5072 5073 if( pStg ) 5074 { 5075 nRet = OpenMainStream( refStrm, nOldBuffSize ); 5076 pIn = &refStrm; 5077 } 5078 else 5079 { 5080 ASSERT(!this, "WinWord 95/97 Reader-Read ohne Storage"); 5081 nRet = ERR_SWG_READ_ERROR; 5082 } 5083 } 5084 5085 if( !nRet ) 5086 { 5087 //JP 18.01.96: Alle Ueberschriften sind normalerweise ohne 5088 // Kapitelnummer. Darum hier explizit abschalten 5089 // weil das Default jetzt wieder auf AN ist. 5090 if (bNew) 5091 { 5092 Reader::SetNoOutlineNum( rDoc ); 5093 // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf. 5094 Reader::ResetFrmFmts( rDoc ); 5095 } 5096 SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc, 5097 rBaseURL, bNew); 5098 try 5099 { 5100 nRet = pRdr->LoadDoc( rPam ); 5101 } 5102 catch( const std::exception& ) 5103 { 5104 nRet = ERR_WW8_NO_WW8_FILE_ERR; 5105 } 5106 delete pRdr; 5107 5108 if( refStrm.Is() ) 5109 { 5110 refStrm->SetBufferSize( nOldBuffSize ); 5111 refStrm.Clear(); 5112 } 5113 else if (pIn) 5114 pIn->ResetError(); 5115 5116 } 5117 return nRet; 5118 } 5119 5120 int WW8Reader::GetReaderType() 5121 { 5122 return SW_STORAGE_READER | SW_STREAM_READER; 5123 } 5124 5125 sal_Bool WW8Reader::HasGlossaries() const 5126 { 5127 return true; 5128 } 5129 5130 sal_Bool WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, sal_Bool bSaveRelFiles) const 5131 { 5132 bool bRet=false; 5133 5134 WW8Reader *pThis = const_cast<WW8Reader *>(this); 5135 5136 sal_uInt16 nOldBuffSize = 32768; 5137 SvStorageStreamRef refStrm; 5138 if (!pThis->OpenMainStream(refStrm, nOldBuffSize)) 5139 { 5140 WW8Glossary aGloss( refStrm, 8, pStg ); 5141 bRet = aGloss.Load( rBlocks, bSaveRelFiles ? true : false); 5142 } 5143 return bRet ? true : false; 5144 } 5145 5146 sal_Bool SwMSDffManager::GetOLEStorageName(long nOLEId, String& rStorageName, 5147 SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const 5148 { 5149 bool bRet = false; 5150 5151 long nPictureId = 0; 5152 if (rReader.pStg) 5153 { 5154 // dann holen wir uns mal ueber den TextBox-PLCF die richtigen 5155 // Char Start-/End-Positionen. In dem Bereich sollte dann 5156 // das EinbettenFeld und die entsprechenden Sprms zu finden 5157 // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id 5158 long nOldPos = rReader.pStrm->Tell(); 5159 { 5160 // #i32596# - consider return value of method 5161 // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method 5162 // wasn't successful. Thus, continue in this case. 5163 // Note: Ask MM for initialization of <nStartCp> and <nEndCp>. 5164 // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>. 5165 WW8_CP nStartCp, nEndCp; 5166 if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp, 5167 static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF), 5168 static_cast<sal_uInt16>(nOLEId & 0xFFFF)) ) 5169 { 5170 WW8PLCFxSaveAll aSave; 5171 memset( &aSave, 0, sizeof( aSave ) ); 5172 rReader.pPlcxMan->SaveAllPLCFx( aSave ); 5173 5174 nStartCp += rReader.nDrawCpO; 5175 nEndCp += rReader.nDrawCpO; 5176 WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF(); 5177 wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion()); 5178 while (nStartCp <= nEndCp && !nPictureId) 5179 { 5180 WW8PLCFxDesc aDesc; 5181 pChp->SeekPos( nStartCp ); 5182 pChp->GetSprms( &aDesc ); 5183 5184 if (aDesc.nSprmsLen && aDesc.pMemPos) // Attribut(e) vorhanden 5185 { 5186 long nLen = aDesc.nSprmsLen; 5187 const sal_uInt8* pSprm = aDesc.pMemPos; 5188 5189 while (nLen >= 2 && !nPictureId) 5190 { 5191 sal_uInt16 nId = aSprmParser.GetSprmId(pSprm); 5192 sal_uInt16 nSL = aSprmParser.GetSprmSize(nId, pSprm); 5193 5194 if( nLen < nSL ) 5195 break; // nicht mehr genug Bytes uebrig 5196 5197 if( 0x6A03 == nId && 0 < nLen ) 5198 { 5199 nPictureId = SVBT32ToUInt32(pSprm + 5200 aSprmParser.DistanceToData(nId)); 5201 bRet = true; 5202 } 5203 pSprm += nSL; 5204 nLen -= nSL; 5205 } 5206 } 5207 nStartCp = aDesc.nEndPos; 5208 } 5209 5210 rReader.pPlcxMan->RestoreAllPLCFx( aSave ); 5211 } 5212 } 5213 rReader.pStrm->Seek( nOldPos ); 5214 } 5215 5216 if( bRet ) 5217 { 5218 rStorageName = '_'; 5219 rStorageName += String::CreateFromInt32(nPictureId); 5220 rSrcStorage = rReader.pStg->OpenSotStorage(CREATE_CONST_ASC( 5221 SL::aObjectPool)); 5222 if (!rReader.mpDocShell) 5223 bRet=false; 5224 else 5225 rDestStorage = rReader.mpDocShell->GetStorage(); 5226 } 5227 return bRet; 5228 } 5229 5230 sal_Bool SwMSDffManager::ShapeHasText(sal_uLong, sal_uLong) const 5231 { 5232 // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer 5233 // Gruppe ist, liegen noch nicht genuegend Informationen vor, um 5234 // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen. 5235 // Also vorsichtshalber mal alle umwandeln: 5236 return true; 5237 } 5238 5239 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const 5240 { 5241 if (nLvl) 5242 --nLvl; 5243 // #i60827# - check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed. 5244 if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) ) 5245 { 5246 return false; 5247 } 5248 mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true); 5249 if (aIter != maApos.end()) 5250 return true; 5251 else 5252 return false; 5253 } 5254 5255 bool SwWW8ImplReader::InEqualApo(int nLvl) const 5256 { 5257 //If we are in a table, see if an apo was inserted at the level below 5258 //the table. 5259 if (nLvl) 5260 --nLvl; 5261 return maApos[nLvl]; 5262 } 5263 5264 namespace sw 5265 { 5266 namespace hack 5267 { 5268 Position::Position(const SwPosition &rPos) 5269 : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex()) 5270 { 5271 } 5272 5273 Position::Position(const Position &rPos) 5274 : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt) 5275 { 5276 } 5277 5278 Position::operator SwPosition() const 5279 { 5280 SwPosition aRet(maPtNode); 5281 aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt); 5282 return aRet; 5283 } 5284 } 5285 } 5286 5287 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 5288