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