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 <vector> 29 #include <list> 30 #include <utility> 31 #include <algorithm> 32 #include <functional> 33 #include <iostream> 34 #if OSL_DEBUG_LEVEL > 0 35 # include <cstdio> 36 #endif 37 38 #include <hintids.hxx> 39 #include <tools/urlobj.hxx> 40 #include <editeng/boxitem.hxx> 41 #include <editeng/cmapitem.hxx> 42 #include <editeng/langitem.hxx> 43 #include <editeng/svxfont.hxx> 44 #include <editeng/lrspitem.hxx> 45 #include <editeng/brshitem.hxx> 46 #include <editeng/fontitem.hxx> 47 #include <editeng/keepitem.hxx> 48 #include <editeng/fhgtitem.hxx> 49 #include <editeng/ulspitem.hxx> 50 #include <editeng/brkitem.hxx> 51 #include <editeng/frmdiritem.hxx> 52 #include <editeng/tstpitem.hxx> 53 #include "svl/urihelper.hxx" 54 #include <svl/whiter.hxx> 55 #include <fmtpdsc.hxx> 56 #include <fmtfsize.hxx> 57 #include <fmtornt.hxx> 58 #include <fmtlsplt.hxx> 59 #include <fmtflcnt.hxx> 60 #include <fmtanchr.hxx> 61 #include <fmtcntnt.hxx> 62 #include <frmatr.hxx> 63 #include <paratr.hxx> 64 #include <txatbase.hxx> 65 #include <fmtinfmt.hxx> 66 #include <fmtrfmrk.hxx> 67 #include <fchrfmt.hxx> 68 #include <fmtautofmt.hxx> 69 #include <charfmt.hxx> 70 #include <tox.hxx> 71 #include <ndtxt.hxx> 72 #include <pam.hxx> 73 #include <doc.hxx> 74 #include <docary.hxx> 75 #include <swtable.hxx> 76 #include <swtblfmt.hxx> 77 #include <section.hxx> 78 #include <pagedesc.hxx> 79 #include <swrect.hxx> 80 #include <reffld.hxx> 81 #include <redline.hxx> 82 #include <wrtswtbl.hxx> 83 #include <htmltbl.hxx> 84 #include <txttxmrk.hxx> 85 #include <fmtline.hxx> 86 #include <fmtruby.hxx> 87 #include <breakit.hxx> 88 #include <txtatr.hxx> 89 #include <fmtsrnd.hxx> 90 #include <fmtrowsplt.hxx> 91 #include <com/sun/star/i18n/ScriptType.hdl> 92 #include <com/sun/star/i18n/WordType.hpp> 93 94 #include <writerfilter/doctok/sprmids.hxx> 95 96 #include "writerhelper.hxx" 97 #include "writerwordglue.hxx" 98 #include <numrule.hxx> 99 #include "wrtww8.hxx" 100 #include "ww8par.hxx" 101 #include <IMark.hxx> 102 #include "ww8attributeoutput.hxx" 103 104 #include <ndgrf.hxx> 105 #include <ndole.hxx> 106 107 #include <cstdio> 108 109 using namespace ::com::sun::star; 110 using namespace ::com::sun::star::i18n; 111 using namespace sw::util; 112 using namespace sw::types; 113 using namespace sw::mark; 114 using namespace nsFieldFlags; 115 116 117 static String lcl_getFieldCode( const IFieldmark* pFieldmark ) { 118 ASSERT(pFieldmark!=NULL, "where is my fieldmark???"); 119 if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) ) { 120 return String::CreateFromAscii(" FORMTEXT "); 121 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) ) { 122 return String::CreateFromAscii(" FORMDROPDOWN "); 123 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ) ) { 124 return String::CreateFromAscii(" FORMCHECKBOX "); 125 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_TOC ) ) { 126 return String::CreateFromAscii(" TOC "); 127 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) ) { 128 return String::CreateFromAscii(" HYPERLINK "); 129 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_PAGEREF ) ) { 130 return String::CreateFromAscii(" PAGEREF "); 131 } else { 132 return pFieldmark->GetFieldname(); 133 } 134 } 135 136 ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) { 137 ASSERT(pFieldmark!=NULL, "where is my fieldmark???"); 138 if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) ) { 139 return ww::eFORMTEXT; 140 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) ) { 141 return ww::eFORMDROPDOWN; 142 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ) ) { 143 return ww::eFORMCHECKBOX; 144 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_TOC ) ) { 145 return ww::eTOC; 146 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) ) { 147 return ww::eHYPERLINK; 148 } else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_PAGEREF ) ) { 149 return ww::ePAGEREF; 150 } else { 151 return ww::eUNKNOWN; 152 } 153 } 154 155 /* */ 156 157 MSWordAttrIter::MSWordAttrIter( MSWordExportBase& rExport ) 158 : pOld( rExport.pChpIter ), m_rExport( rExport ) 159 { 160 m_rExport.pChpIter = this; 161 } 162 163 MSWordAttrIter::~MSWordAttrIter() 164 { 165 m_rExport.pChpIter = pOld; 166 } 167 168 // Die Klasse SwAttrIter ist eine Hilfe zum Aufbauen der Fkp.chpx. 169 // Dabei werden nur Zeichen-Attribute beachtet; Absatz-Attribute brauchen 170 // diese Behandlung nicht. 171 // Die Absatz- und Textattribute des Writers kommen rein, und es wird 172 // mit Where() die naechste Position geliefert, an der sich die Attribute 173 // aendern. IsTxtAtr() sagt, ob sich an der mit Where() gelieferten Position 174 // ein Attribut ohne Ende und mit \xff im Text befindet. 175 // Mit OutAttr() werden die Attribute an der angegebenen SwPos 176 // ausgegeben. 177 178 class WW8SwAttrIter : public MSWordAttrIter 179 { 180 private: 181 const SwTxtNode& rNd; 182 183 CharRuns maCharRuns; 184 cCharRunIter maCharRunIter; 185 186 rtl_TextEncoding meChrSet; 187 sal_uInt16 mnScript; 188 bool mbCharIsRTL; 189 190 const SwRedline* pCurRedline; 191 xub_StrLen nAktSwPos; 192 sal_uInt16 nCurRedlinePos; 193 194 bool mbParaIsRTL; 195 196 const SwFmtDrop &mrSwFmtDrop; 197 198 sw::Frames maFlyFrms; // #i2916# 199 sw::FrameIter maFlyIter; 200 201 xub_StrLen SearchNext( xub_StrLen nStartPos ); 202 void FieldVanish( const String& rTxt ); 203 204 void OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool bStart); 205 206 void IterToCurrent(); 207 208 //No copying 209 WW8SwAttrIter(const WW8SwAttrIter&); 210 WW8SwAttrIter& operator=(const WW8SwAttrIter&); 211 public: 212 WW8SwAttrIter( MSWordExportBase& rWr, const SwTxtNode& rNd ); 213 214 bool IsTxtAttr( xub_StrLen nSwPos ); 215 bool IsRedlineAtEnd( xub_StrLen nPos ) const; 216 bool IsDropCap( int nSwPos ); 217 bool RequiresImplicitBookmark(); 218 219 void NextPos() { nAktSwPos = SearchNext( nAktSwPos + 1 ); } 220 221 void OutAttr( xub_StrLen nSwPos ); 222 virtual const SfxPoolItem* HasTextItem( sal_uInt16 nWhich ) const; 223 virtual const SfxPoolItem& GetItem( sal_uInt16 nWhich ) const; 224 int OutAttrWithRange(xub_StrLen nPos); 225 const SwRedlineData* GetRedline( xub_StrLen nPos ); 226 void OutFlys(xub_StrLen nSwPos); 227 228 xub_StrLen WhereNext() const { return nAktSwPos; } 229 sal_uInt16 GetScript() const { return mnScript; } 230 bool IsCharRTL() const { return mbCharIsRTL; } 231 bool IsParaRTL() const { return mbParaIsRTL; } 232 rtl_TextEncoding GetCharSet() const { return meChrSet; } 233 String GetSnippet(const String &rStr, xub_StrLen nAktPos, 234 xub_StrLen nLen) const; 235 const SwFmtDrop& GetSwFmtDrop() const { return mrSwFmtDrop; } 236 }; 237 238 class sortswflys : 239 public std::binary_function<const sw::Frame&, const sw::Frame&, bool> 240 { 241 public: 242 bool operator()(const sw::Frame &rOne, const sw::Frame &rTwo) const 243 { 244 return rOne.GetPosition() < rTwo.GetPosition(); 245 } 246 }; 247 248 void WW8SwAttrIter::IterToCurrent() 249 { 250 ASSERT(maCharRuns.begin() != maCharRuns.end(), "Impossible"); 251 mnScript = maCharRunIter->mnScript; 252 meChrSet = maCharRunIter->meCharSet; 253 mbCharIsRTL = maCharRunIter->mbRTL; 254 } 255 256 WW8SwAttrIter::WW8SwAttrIter(MSWordExportBase& rWr, const SwTxtNode& rTxtNd) : 257 MSWordAttrIter(rWr), 258 rNd(rTxtNd), 259 maCharRuns(GetPseudoCharRuns(rTxtNd, 0, !rWr.HackIsWW8OrHigher())), 260 pCurRedline(0), 261 nAktSwPos(0), 262 nCurRedlinePos(USHRT_MAX), 263 mrSwFmtDrop(rTxtNd.GetSwAttrSet().GetDrop()) 264 { 265 266 SwPosition aPos(rTxtNd); 267 if (FRMDIR_HORI_RIGHT_TOP == rWr.pDoc->GetTextDirection(aPos)) 268 mbParaIsRTL = true; 269 else 270 mbParaIsRTL = false; 271 272 maCharRunIter = maCharRuns.begin(); 273 IterToCurrent(); 274 275 /* 276 #i2916# 277 Get list of any graphics which may be anchored from this paragraph. 278 */ 279 maFlyFrms = GetFramesInNode(rWr.maFrames, rNd); 280 std::sort(maFlyFrms.begin(), maFlyFrms.end(), sortswflys()); 281 282 /* 283 #i18480# 284 If we are inside a frame then anything anchored inside this frame can 285 only be supported by word anchored inline ("as character"), so force 286 this in the supportable case. 287 */ 288 if (rWr.HackIsWW8OrHigher() && rWr.bInWriteEscher) 289 { 290 std::for_each(maFlyFrms.begin(), maFlyFrms.end(), 291 std::mem_fun_ref(&sw::Frame::ForceTreatAsInline)); 292 } 293 294 maFlyIter = maFlyFrms.begin(); 295 296 if ( m_rExport.pDoc->GetRedlineTbl().Count() ) 297 { 298 SwPosition aPosition( rNd, SwIndex( (SwTxtNode*)&rNd ) ); 299 pCurRedline = m_rExport.pDoc->GetRedline( aPosition, &nCurRedlinePos ); 300 } 301 302 nAktSwPos = SearchNext(1); 303 } 304 305 xub_StrLen lcl_getMinPos( xub_StrLen pos1, xub_StrLen pos2 ) 306 { 307 xub_StrLen min = STRING_NOTFOUND; 308 if ( pos1 == STRING_NOTFOUND && pos2 != STRING_NOTFOUND ) 309 min = pos2; 310 else if ( pos2 == STRING_NOTFOUND && pos1 != STRING_NOTFOUND ) 311 min = pos1; 312 else if ( pos2 != STRING_NOTFOUND && pos2 != STRING_NOTFOUND ) 313 { 314 if ( pos1 < pos2 ) 315 min = pos1; 316 else 317 min = pos2; 318 } 319 320 return min; 321 } 322 323 xub_StrLen WW8SwAttrIter::SearchNext( xub_StrLen nStartPos ) 324 { 325 xub_StrLen nPos; 326 xub_StrLen nMinPos = STRING_MAXLEN; 327 xub_StrLen i=0; 328 329 const String aTxt = rNd.GetTxt(); 330 xub_StrLen fieldEndPos = aTxt.Search(CH_TXT_ATR_FIELDEND, nStartPos); 331 xub_StrLen fieldStartPos = aTxt.Search(CH_TXT_ATR_FIELDSTART, nStartPos); 332 xub_StrLen formElementPos = aTxt.Search(CH_TXT_ATR_FORMELEMENT, nStartPos); 333 334 xub_StrLen pos = lcl_getMinPos( fieldEndPos, fieldStartPos ); 335 pos = lcl_getMinPos( pos, formElementPos ); 336 337 if (pos!=STRING_NOTFOUND) 338 nMinPos=pos; 339 340 // first the redline, then the attributes 341 if( pCurRedline ) 342 { 343 const SwPosition* pEnd = pCurRedline->End(); 344 if (pEnd->nNode == rNd && ((i = pEnd->nContent.GetIndex()) >= nStartPos) && i < nMinPos ) 345 nMinPos = i; 346 } 347 348 if ( nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count() ) 349 { 350 // nCurRedlinePos point to the next redline 351 nPos = nCurRedlinePos; 352 if( pCurRedline ) 353 ++nPos; 354 355 for ( ; nPos < m_rExport.pDoc->GetRedlineTbl().Count(); ++nPos ) 356 { 357 const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nPos ]; 358 359 const SwPosition* pStt = pRedl->Start(); 360 const SwPosition* pEnd = pStt == pRedl->GetPoint() 361 ? pRedl->GetMark() 362 : pRedl->GetPoint(); 363 364 if( pStt->nNode == rNd ) 365 { 366 if( ( i = pStt->nContent.GetIndex() ) >= nStartPos && 367 i < nMinPos ) 368 nMinPos = i; 369 } 370 else 371 break; 372 373 if( pEnd->nNode == rNd && 374 ( i = pEnd->nContent.GetIndex() ) < nMinPos && 375 i >= nStartPos ) 376 nMinPos = i; 377 } 378 } 379 380 381 if (mrSwFmtDrop.GetWholeWord() && nStartPos <= rNd.GetDropLen(0)) 382 nMinPos = rNd.GetDropLen(0); 383 else if(nStartPos <= mrSwFmtDrop.GetChars()) 384 nMinPos = mrSwFmtDrop.GetChars(); 385 386 if(const SwpHints* pTxtAttrs = rNd.GetpSwpHints()) 387 { 388 389 // kann noch optimiert werden, wenn ausgenutzt wird, dass die TxtAttrs 390 // nach der Anfangsposition geordnet sind. Dann muessten 391 // allerdings noch 2 Indices gemerkt werden 392 for( i = 0; i < pTxtAttrs->Count(); i++ ) 393 { 394 const SwTxtAttr* pHt = (*pTxtAttrs)[i]; 395 nPos = *pHt->GetStart(); // gibt erstes Attr-Zeichen 396 if( nPos >= nStartPos && nPos <= nMinPos ) 397 nMinPos = nPos; 398 399 if( pHt->GetEnd() ) // Attr mit Ende 400 { 401 nPos = *pHt->GetEnd(); // gibt letztes Attr-Zeichen + 1 402 if( nPos >= nStartPos && nPos <= nMinPos ) 403 nMinPos = nPos; 404 } 405 if (pHt->HasDummyChar()) 406 { 407 // pos + 1 because of CH_TXTATR in Text 408 nPos = *pHt->GetStart() + 1; 409 if( nPos >= nStartPos && nPos <= nMinPos ) 410 nMinPos = nPos; 411 } 412 } 413 } 414 415 if (maCharRunIter != maCharRuns.end()) 416 { 417 if (maCharRunIter->mnEndPos < nMinPos) 418 nMinPos = maCharRunIter->mnEndPos; 419 IterToCurrent(); 420 } 421 422 /* 423 #i2916# 424 Check to see if there are any graphics anchored to characters in this 425 paragraph's text. Set nMinPos to 1 past the placement for anchored to 426 character because anchors in Word appear after the character they are 427 anchored to. 428 */ 429 if (maFlyIter != maFlyFrms.end()) 430 { 431 const SwPosition &rAnchor = maFlyIter->GetPosition(); 432 433 nPos = rAnchor.nContent.GetIndex(); 434 if (nPos >= nStartPos && nPos <= nMinPos) 435 nMinPos = nPos; 436 437 if (maFlyIter->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR) 438 { 439 ++nPos; 440 if (nPos >= nStartPos && nPos <= nMinPos) 441 nMinPos = nPos; 442 } 443 } 444 445 //nMinPos found and not going to change at this point 446 447 if (maCharRunIter != maCharRuns.end()) 448 { 449 if (maCharRunIter->mnEndPos == nMinPos) 450 ++maCharRunIter; 451 } 452 453 return nMinPos; 454 } 455 456 void WW8SwAttrIter::OutAttr( xub_StrLen nSwPos ) 457 { 458 m_rExport.AttrOutput().RTLAndCJKState( IsCharRTL(), GetScript() ); 459 460 /* 461 Depending on whether text is in CTL/CJK or Western, get the id of that 462 script, the idea is that the font that is actually in use to render this 463 range of text ends up in pFont 464 */ 465 sal_uInt16 nFontId = GetWhichOfScript( RES_CHRATR_FONT, GetScript() ); 466 467 const SvxFontItem &rParentFont = ItemGet<SvxFontItem>( 468 (const SwTxtFmtColl&)rNd.GetAnyFmtColl(), nFontId); 469 const SvxFontItem *pFont = &rParentFont; 470 471 SfxItemSet aExportSet(*rNd.GetSwAttrSet().GetPool(), 472 RES_CHRATR_BEGIN, RES_TXTATR_END - 1); 473 474 //The hard formatting properties that affect the entire paragraph 475 if (rNd.HasSwAttrSet()) 476 { 477 sal_Bool bDeep = sal_False; 478 // only copy hard attributes - bDeep = false 479 aExportSet.Set(rNd.GetSwAttrSet(), bDeep); 480 // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet: 481 const SvxFontItem &rNdFont = ItemGet<SvxFontItem>(rNd.GetSwAttrSet(), nFontId); 482 pFont = &rNdFont; 483 aExportSet.ClearItem(nFontId); 484 } 485 486 //The additional hard formatting properties that affect this range in the 487 //paragraph 488 sw::PoolItems aRangeItems; 489 if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints()) 490 { 491 for (xub_StrLen i = 0; i < pTxtAttrs->Count(); ++i) 492 { 493 const SwTxtAttr* pHt = (*pTxtAttrs)[i]; 494 const xub_StrLen* pEnd = pHt->GetEnd(); 495 496 if (pEnd ? ( nSwPos >= *pHt->GetStart() && nSwPos < *pEnd) 497 : nSwPos == *pHt->GetStart() ) 498 { 499 sal_uInt16 nWhich = pHt->GetAttr().Which(); 500 if (nWhich == RES_TXTATR_AUTOFMT) 501 { 502 const SwFmtAutoFmt& rAutoFmt = static_cast<const SwFmtAutoFmt&>(pHt->GetAttr()); 503 const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle(); 504 SfxWhichIter aIter( *pSet ); 505 const SfxPoolItem* pItem; 506 sal_uInt16 nWhichId = aIter.FirstWhich(); 507 while( nWhichId ) 508 { 509 if( SFX_ITEM_SET == pSet->GetItemState( nWhichId, sal_False, &pItem )) 510 { 511 if (nWhichId == nFontId) 512 pFont = &(item_cast<SvxFontItem>(*pItem)); 513 else 514 aRangeItems[nWhichId] = pItem; 515 } 516 nWhichId = aIter.NextWhich(); 517 } 518 } 519 else 520 aRangeItems[nWhich] = (&(pHt->GetAttr())); 521 } 522 else if (nSwPos < *pHt->GetStart()) 523 break; 524 } 525 } 526 527 /* 528 For #i24291# we need to explictly remove any properties from the 529 aExportSet which a SwCharFmt would override, we can't rely on word doing 530 this for us like writer does 531 */ 532 const SwFmtCharFmt *pCharFmtItem = 533 HasItem< SwFmtCharFmt >( aRangeItems, RES_TXTATR_CHARFMT ); 534 if ( pCharFmtItem ) 535 ClearOverridesFromSet( *pCharFmtItem, aExportSet ); 536 537 sw::PoolItems aExportItems; 538 GetPoolItems( aExportSet, aExportItems, false ); 539 540 sw::cPoolItemIter aEnd = aRangeItems.end(); 541 for ( sw::cPoolItemIter aI = aRangeItems.begin(); aI != aEnd; ++aI ) 542 aExportItems[aI->first] = aI->second; 543 544 if ( !aExportItems.empty() ) 545 { 546 const SwModify* pOldMod = m_rExport.pOutFmtNode; 547 m_rExport.pOutFmtNode = &rNd; 548 m_rExport.m_aCurrentCharPropStarts.push( nSwPos ); 549 550 m_rExport.ExportPoolItemsToCHP( aExportItems, GetScript() ); 551 552 // HasTextItem nur in dem obigen Bereich erlaubt 553 m_rExport.m_aCurrentCharPropStarts.pop(); 554 m_rExport.pOutFmtNode = pOldMod; 555 } 556 557 ASSERT( pFont, "must be *some* font associated with this txtnode" ); 558 if ( pFont ) 559 { 560 SvxFontItem aFont( *pFont ); 561 562 /* 563 If we are a nonunicode aware format then we set the charset we want to 564 use for export of this range. If necessary this will generate a pseudo 565 font to use for this range. 566 567 So now we are guaranteed to have a font with the correct charset set 568 for WW6/95 which will match the script we have exported this range in, 569 this makes older nonunicode aware versions of word display the correct 570 characters. 571 */ 572 if ( !m_rExport.HackIsWW8OrHigher() ) 573 aFont.SetCharSet( GetCharSet() ); 574 575 if ( rParentFont != aFont ) 576 m_rExport.AttrOutput().OutputItem( aFont ); 577 } 578 } 579 580 void WW8SwAttrIter::OutFlys(xub_StrLen nSwPos) 581 { 582 /* 583 #i2916# 584 May have an anchored graphic to be placed, loop through sorted array 585 and output all at this position 586 */ 587 while ( maFlyIter != maFlyFrms.end() ) 588 { 589 const SwPosition &rAnchor = maFlyIter->GetPosition(); 590 xub_StrLen nPos = rAnchor.nContent.GetIndex(); 591 592 if ( nPos != nSwPos ) 593 break; 594 else 595 { 596 m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter ); 597 ++maFlyIter; 598 } 599 } 600 } 601 602 bool WW8SwAttrIter::IsTxtAttr( xub_StrLen nSwPos ) 603 { 604 // search for attrs with CH_TXTATR 605 if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints()) 606 { 607 for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i) 608 { 609 const SwTxtAttr* pHt = (*pTxtAttrs)[i]; 610 if ( pHt->HasDummyChar() && (*pHt->GetStart() == nSwPos) ) 611 return true; 612 } 613 } 614 615 return false; 616 } 617 618 bool WW8SwAttrIter::IsDropCap( int nSwPos ) 619 { 620 // see if the current position falls on a DropCap 621 int nDropChars = mrSwFmtDrop.GetChars(); 622 bool bWholeWord = mrSwFmtDrop.GetWholeWord(); 623 if (bWholeWord) 624 { 625 short nWordLen = rNd.GetDropLen(0); 626 if(nSwPos == nWordLen && nSwPos != 0) 627 return true; 628 } 629 else 630 { 631 if (nSwPos == nDropChars && nSwPos != 0) 632 return true; 633 } 634 return false; 635 } 636 637 bool WW8SwAttrIter::RequiresImplicitBookmark() 638 { 639 SwImplBookmarksIter bkmkIterEnd = m_rExport.maImplicitBookmarks.end(); 640 for ( SwImplBookmarksIter aIter = m_rExport.maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter ) 641 { 642 sal_uLong sample = aIter->second; 643 644 if ( sample == rNd.GetIndex() ) 645 return true; 646 } 647 return false; 648 } 649 650 // HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline 651 // und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion, 652 // die dann ueber HasItem() nach anderen Items an der 653 // Attribut-Anfangposition fragen kann. 654 // Es koennen nur Attribute mit Ende abgefragt werden. 655 // Es wird mit bDeep gesucht 656 const SfxPoolItem* WW8SwAttrIter::HasTextItem( sal_uInt16 nWhich ) const 657 { 658 const SfxPoolItem* pRet = 0; 659 const SwpHints* pTxtAttrs = rNd.GetpSwpHints(); 660 xub_StrLen nTmpSwPos = m_rExport.m_aCurrentCharPropStarts.top(); 661 if (pTxtAttrs) 662 { 663 for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i) 664 { 665 const SwTxtAttr* pHt = (*pTxtAttrs)[i]; 666 const SfxPoolItem* pItem = &pHt->GetAttr(); 667 const xub_StrLen* pAtrEnd = 0; 668 if( 0 != ( pAtrEnd = pHt->GetEnd() ) && // nur Attr mit Ende 669 nWhich == pItem->Which() && // 670 nTmpSwPos >= *pHt->GetStart() && nTmpSwPos < *pAtrEnd ) 671 { 672 pRet = pItem; // gefunden 673 break; 674 } 675 else if (nTmpSwPos < *pHt->GetStart()) 676 break; // dann kommt da nichts mehr 677 } 678 } 679 return pRet; 680 } 681 682 void WW8Export::GetCurrentItems(WW8Bytes& rItems) const 683 { 684 sal_uInt16 nEnd = pO ? pO->Count() : 0; 685 for (sal_uInt16 nI = 0; nI < nEnd; ++nI) 686 rItems.Insert((*pO)[nI], rItems.Count()); 687 } 688 689 const SfxPoolItem& WW8SwAttrIter::GetItem(sal_uInt16 nWhich) const 690 { 691 const SfxPoolItem* pRet = HasTextItem(nWhich); 692 return pRet ? *pRet : rNd.SwCntntNode::GetAttr(nWhich); 693 } 694 695 void WW8AttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby ) 696 { 697 String aStr( FieldString( ww::eEQ ) ); 698 aStr.APPEND_CONST_ASC( "\\* jc" ); 699 sal_Int32 nJC = 0; 700 sal_Char cDirective = 0; 701 switch ( rRuby.GetAdjustment() ) 702 { 703 case 0: 704 nJC = 3; 705 cDirective = 'l'; 706 break; 707 case 1: 708 //defaults to 0 709 break; 710 case 2: 711 nJC = 4; 712 cDirective = 'r'; 713 break; 714 case 3: 715 nJC = 1; 716 cDirective = 'd'; 717 break; 718 case 4: 719 nJC = 2; 720 cDirective = 'd'; 721 break; 722 default: 723 ASSERT( !this,"Unhandled Ruby justication code" ); 724 break; 725 } 726 aStr += String::CreateFromInt32( nJC ); 727 728 /* 729 MS needs to know the name and size of the font used in the ruby item, 730 but we coud have written it in a mixture of asian and western 731 scripts, and each of these can be a different font and size than the 732 other, so we make a guess based upon the first character of the text, 733 defaulting to asian. 734 */ 735 sal_uInt16 nRubyScript; 736 if( pBreakIt->GetBreakIter().is() ) 737 nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rRuby.GetText(), 0); 738 else 739 nRubyScript = i18n::ScriptType::ASIAN; 740 741 const SwTxtRuby* pRubyTxt = rRuby.GetTxtRuby(); 742 const SwCharFmt* pFmt = pRubyTxt ? pRubyTxt->GetCharFmt() : 0; 743 String sFamilyName; 744 long nHeight; 745 if ( pFmt ) 746 { 747 const SvxFontItem &rFont = ItemGet< SvxFontItem >( *pFmt, 748 GetWhichOfScript(RES_CHRATR_FONT,nRubyScript) ); 749 sFamilyName = rFont.GetFamilyName(); 750 751 const SvxFontHeightItem &rHeight = ItemGet< SvxFontHeightItem >( *pFmt, 752 GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) ); 753 nHeight = rHeight.GetHeight(); 754 } 755 else 756 { 757 /*Get defaults if no formatting on ruby text*/ 758 759 const SfxItemPool *pPool = rNode.GetSwAttrSet().GetPool(); 760 const SfxItemPool &rPool = pPool ? *pPool : m_rWW8Export.pDoc->GetAttrPool(); 761 762 const SvxFontItem &rFont = DefaultItemGet< SvxFontItem >( rPool, 763 GetWhichOfScript( RES_CHRATR_FONT,nRubyScript ) ); 764 sFamilyName = rFont.GetFamilyName(); 765 766 const SvxFontHeightItem &rHeight = DefaultItemGet< SvxFontHeightItem > 767 ( rPool, GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) ); 768 nHeight = rHeight.GetHeight(); 769 } 770 nHeight = (nHeight + 5)/10; 771 772 aStr.APPEND_CONST_ASC( " \\* \"Font:" ); 773 aStr.Append( sFamilyName ); 774 aStr.APPEND_CONST_ASC( "\" \\* hps" ); 775 aStr += String::CreateFromInt32( nHeight ); 776 aStr.APPEND_CONST_ASC( " \\o" ); 777 if ( cDirective ) 778 { 779 aStr.APPEND_CONST_ASC( "\\a" ); 780 aStr.Append( cDirective ); 781 } 782 aStr.APPEND_CONST_ASC( "(\\s\\up " ); 783 784 785 if ( pBreakIt->GetBreakIter().is() ) 786 nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rNode.GetTxt(), 787 *( pRubyTxt->GetStart() ) ); 788 else 789 nRubyScript = i18n::ScriptType::ASIAN; 790 791 const SwAttrSet& rSet = rNode.GetSwAttrSet(); 792 const SvxFontHeightItem &rHeightItem = 793 ( const SvxFontHeightItem& )rSet.Get( 794 GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) ); 795 nHeight = (rHeightItem.GetHeight() + 10)/20-1; 796 aStr += String::CreateFromInt32(nHeight); 797 aStr += '('; 798 aStr += rRuby.GetText(); 799 aStr.APPEND_CONST_ASC( ");" ); 800 m_rWW8Export.OutputField( 0, ww::eEQ, aStr, 801 WRITEFIELD_START | WRITEFIELD_CMD_START ); 802 } 803 804 void WW8AttributeOutput::EndRuby() 805 { 806 m_rWW8Export.WriteChar( ')' ); 807 m_rWW8Export.OutputField( 0, ww::eEQ, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE ); 808 } 809 810 /*#i15387# Better ideas welcome*/ 811 String &TruncateBookmark( String &rRet ) 812 { 813 if ( rRet.Len() > 40 ) 814 rRet.Erase( 40 ); 815 ASSERT( rRet.Len() <= 40, "Word cannot have bookmarks longer than 40 chars" ); 816 return rRet; 817 } 818 819 bool AttributeOutputBase::AnalyzeURL( const String& rUrl, const String& /*rTarget*/, String* pLinkURL, String* pMark ) 820 { 821 bool bBookMarkOnly = false; 822 823 INetURLObject aURL( rUrl ); 824 String sMark; 825 String sURL; 826 827 if ( rUrl.Len() > 1 && rUrl.GetChar(0) == INET_MARK_TOKEN ) 828 { 829 sMark = BookmarkToWriter( rUrl.Copy(1) ); 830 831 xub_StrLen nPos = sMark.SearchBackward( cMarkSeperator ); 832 833 String sRefType( sMark.Copy( nPos+1 ) ); 834 sRefType.EraseAllChars(); 835 836 // i21465 Only interested in outline references 837 if ( sRefType.EqualsAscii( pMarkToOutline ) ) 838 { 839 String sLink = sMark.Copy(0, nPos); 840 SwImplBookmarksIter bkmkIterEnd = GetExport().maImplicitBookmarks.end(); 841 for ( SwImplBookmarksIter aIter = GetExport().maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter ) 842 { 843 String bkmkName = aIter->first; 844 845 if ( bkmkName == sLink ) 846 { 847 sMark = String( RTL_CONSTASCII_STRINGPARAM( "_toc" ) ); 848 sMark += String::CreateFromInt32( aIter->second ); 849 } 850 } 851 } 852 } 853 else 854 { 855 sURL = aURL.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS ); 856 sMark = aURL.GetMark( INetURLObject::DECODE_UNAMBIGUOUS ); 857 858 } 859 860 if ( sMark.Len() && !sURL.Len() ) 861 bBookMarkOnly = true; 862 863 864 865 *pMark = sMark; 866 *pLinkURL = sURL; 867 return bBookMarkOnly; 868 } 869 870 bool WW8AttributeOutput::AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark ) 871 { 872 bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark ); 873 874 String sURL = *pLinkURL; 875 String sMark = *pMark; 876 877 if ( sURL.Len() ) 878 sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL ); 879 880 if ( bBookMarkOnly ) 881 sURL = FieldString( ww::eHYPERLINK ); 882 else 883 { 884 String sFld( FieldString( ww::eHYPERLINK ) ); 885 sFld.APPEND_CONST_ASC( "\"" ); 886 sURL.Insert( sFld, 0 ); 887 sURL += '\"'; 888 } 889 890 if ( sMark.Len() ) 891 ( ( sURL.APPEND_CONST_ASC( " \\l \"" ) ) += sMark ) += '\"'; 892 893 if ( rTarget.Len() ) 894 ( sURL.APPEND_CONST_ASC( " \\n " ) ) += rTarget; 895 896 *pLinkURL = sURL; 897 *pMark = sMark; 898 899 return bBookMarkOnly; 900 } 901 902 bool WW8AttributeOutput::StartURL( const String &rUrl, const String &rTarget ) 903 { 904 // hyperlinks only in WW8 905 if ( !m_rWW8Export.bWrtWW8 ) 906 return false; 907 908 INetURLObject aURL( rUrl ); 909 String sURL; 910 String sMark; 911 912 bool bBookMarkOnly = AnalyzeURL( rUrl, rTarget, &sURL, &sMark ); 913 914 915 m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_START | WRITEFIELD_CMD_START ); 916 917 // write the refence to the "picture" structure 918 sal_uLong nDataStt = m_rWW8Export.pDataStrm->Tell(); 919 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() ); 920 921 // WinWord 2000 doesn't write this - so its a temp solution by W97 ? 922 m_rWW8Export.WriteChar( 0x01 ); 923 924 static sal_uInt8 aArr1[] = { 925 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation 926 927 0x06, 0x08, 0x01, // sprmCFData 928 0x55, 0x08, 0x01, // sprmCFSpec 929 0x02, 0x08, 0x01 // sprmCFFldVanish 930 }; 931 sal_uInt8* pDataAdr = aArr1 + 2; 932 Set_UInt32( pDataAdr, nDataStt ); 933 934 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), sizeof( aArr1 ), aArr1 ); 935 936 m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_CMD_END ); 937 938 // now write the picture structur 939 sURL = aURL.GetURLNoMark(); 940 941 //all links end up in the data stream as absolute references. 942 bool bAbsolute = !bBookMarkOnly; 943 944 static sal_uInt8 __READONLY_DATA aURLData1[] = { 945 0,0,0,0, // len of struct 946 0x44,0, // the start of "next" data 947 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! 948 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | 949 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | 950 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | 951 0,0,0,0, // / 952 }; 953 static sal_uInt8 __READONLY_DATA MAGIC_A[] = { 954 // start of "next" data 955 0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11, 956 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B 957 }; 958 959 m_rWW8Export.pDataStrm->Write( aURLData1, sizeof( aURLData1 ) ); 960 sal_uInt8 nAnchor = 0x00; 961 if ( sMark.Len() ) 962 nAnchor = 0x08; 963 m_rWW8Export.pDataStrm->Write( &nAnchor, 1 ); 964 m_rWW8Export.pDataStrm->Write( MAGIC_A, sizeof(MAGIC_A) ); 965 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 0x00000002); 966 sal_uInt32 nFlag = bBookMarkOnly ? 0 : 0x01; 967 if ( bAbsolute ) 968 nFlag |= 0x02; 969 if ( sMark.Len() ) 970 nFlag |= 0x08; 971 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nFlag ); 972 973 INetProtocol eProto = aURL.GetProtocol(); 974 if ( eProto == INET_PROT_FILE ) 975 { 976 // version 1 (for a document) 977 978 static sal_uInt8 __READONLY_DATA MAGIC_C[] = { 979 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 980 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 981 0x00, 0x00 982 }; 983 984 static sal_uInt8 __READONLY_DATA MAGIC_D[] = { 985 0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 988 }; 989 990 // save the links to files as relative 991 sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL ); 992 if ( sURL.EqualsAscii( "/", 0, 1 ) ) 993 sURL = aURL.PathToFileName(); 994 995 // special case for the absolute windows names 996 // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc') 997 sal_Unicode aDrive = ( sURL.Len() > 1 )? sURL.GetChar( 1 ): 0; 998 if ( sURL.EqualsAscii( "/", 0, 1 ) && 999 ( ( aDrive >= 'A' && aDrive <= 'Z' ) || ( aDrive >= 'a' && aDrive <= 'z' ) ) && 1000 sURL.EqualsAscii( ":", 2, 1 ) ) 1001 { 1002 sURL.Erase( 0, 1 ); 1003 sURL.SearchAndReplaceAll( '/', '\\' ); 1004 } 1005 1006 m_rWW8Export.pDataStrm->Write( MAGIC_C, sizeof(MAGIC_C) ); 1007 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sURL.Len()+1 ); 1008 SwWW8Writer::WriteString8( *m_rWW8Export.pDataStrm, sURL, true, 1009 RTL_TEXTENCODING_MS_1252 ); 1010 m_rWW8Export.pDataStrm->Write( MAGIC_D, sizeof( MAGIC_D ) ); 1011 1012 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.Len() + 6 ); 1013 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.Len() ); 1014 SwWW8Writer::WriteShort( *m_rWW8Export.pDataStrm, 3 ); 1015 SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, false ); 1016 } 1017 else if ( eProto != INET_PROT_NOT_VALID ) 1018 { 1019 // version 2 (simple url) 1020 // an write some data to the data stream, but dont ask 1021 // what the data mean, except for the URL. 1022 // The First piece is the WW8_PIC structure. 1023 // 1024 static sal_uInt8 __READONLY_DATA MAGIC_B[] = { 1025 0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11, 1026 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B 1027 }; 1028 1029 m_rWW8Export.pDataStrm->Write( MAGIC_B, sizeof(MAGIC_B) ); 1030 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2 * ( sURL.Len() + 1 ) ); 1031 SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, true ); 1032 } 1033 1034 if ( sMark.Len() ) 1035 { 1036 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sMark.Len()+1 ); 1037 SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sMark, true ); 1038 } 1039 SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nDataStt, 1040 m_rWW8Export.pDataStrm->Tell() - nDataStt ); 1041 1042 return true; 1043 } 1044 1045 bool WW8AttributeOutput::EndURL() 1046 { 1047 // hyperlinks only in WW8 1048 if ( !m_rWW8Export.bWrtWW8 ) 1049 return false; 1050 1051 m_rWW8Export.OutputField( 0, ww::eHYPERLINK, aEmptyStr, WRITEFIELD_CLOSE ); 1052 1053 return true; 1054 } 1055 1056 String BookmarkToWord(const String &rBookmark) 1057 { 1058 String sRet(INetURLObject::encode(rBookmark, 1059 INetURLObject::PART_REL_SEGMENT_EXTRA, '%', 1060 INetURLObject::ENCODE_ALL, RTL_TEXTENCODING_ASCII_US)); 1061 return TruncateBookmark(sRet); 1062 } 1063 1064 String BookmarkToWriter(const String &rBookmark) 1065 { 1066 return INetURLObject::decode(rBookmark, '%', 1067 INetURLObject::DECODE_UNAMBIGUOUS, RTL_TEXTENCODING_ASCII_US); 1068 } 1069 1070 void WW8SwAttrIter::OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool) 1071 { 1072 if ( m_rExport.HasRefToObject( REF_SETREFATTR, &rAttr.GetRefName(), 0 ) ) 1073 m_rExport.AppendBookmark( m_rExport.GetBookmarkName( REF_SETREFATTR, 1074 &rAttr.GetRefName(), 0 )); 1075 } 1076 1077 void WW8AttributeOutput::FieldVanish( const String& rTxt, ww::eField /*eType*/ ) 1078 { 1079 WW8Bytes aItems; 1080 m_rWW8Export.GetCurrentItems( aItems ); 1081 1082 // sprmCFFldVanish 1083 if ( m_rWW8Export.bWrtWW8 ) 1084 SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish ); 1085 else 1086 aItems.Insert( 67, aItems.Count() ); 1087 aItems.Insert( 1, aItems.Count() ); 1088 1089 sal_uInt16 nStt_sprmCFSpec = aItems.Count(); 1090 1091 // sprmCFSpec -- fSpec-Attribut true 1092 if ( m_rWW8Export.bWrtWW8 ) 1093 SwWW8Writer::InsUInt16( aItems, 0x855 ); 1094 else 1095 aItems.Insert( 117, aItems.Count() ); 1096 aItems.Insert( 1, aItems.Count() ); 1097 1098 m_rWW8Export.WriteChar( '\x13' ); 1099 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(), 1100 aItems.GetData() ); 1101 m_rWW8Export.OutSwString( rTxt, 0, rTxt.Len(), m_rWW8Export.IsUnicode(), 1102 RTL_TEXTENCODING_MS_1252 ); 1103 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), nStt_sprmCFSpec, 1104 aItems.GetData() ); 1105 m_rWW8Export.WriteChar( '\x15' ); 1106 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(), 1107 aItems.GetData() ); 1108 } 1109 1110 void AttributeOutputBase::TOXMark( const SwTxtNode& rNode, const SwTOXMark& rAttr ) 1111 { 1112 // its a field; so get the Text form the Node and build the field 1113 String sTxt; 1114 ww::eField eType = ww::eNONE; 1115 1116 const SwTxtTOXMark& rTxtTOXMark = *rAttr.GetTxtTOXMark(); 1117 const xub_StrLen* pTxtEnd = rTxtTOXMark.GetEnd(); 1118 if ( pTxtEnd ) // has range? 1119 { 1120 sTxt = rNode.GetExpandTxt( *rTxtTOXMark.GetStart(), 1121 *pTxtEnd - *rTxtTOXMark.GetStart() ); 1122 } 1123 else 1124 sTxt = rAttr.GetAlternativeText(); 1125 1126 switch ( rAttr.GetTOXType()->GetType() ) 1127 { 1128 case TOX_INDEX: 1129 eType = ww::eXE; 1130 if ( rAttr.GetPrimaryKey().Len() ) 1131 { 1132 if ( rAttr.GetSecondaryKey().Len() ) 1133 { 1134 sTxt.Insert( ':', 0 ); 1135 sTxt.Insert( rAttr.GetSecondaryKey(), 0 ); 1136 } 1137 1138 sTxt.Insert( ':', 0 ); 1139 sTxt.Insert( rAttr.GetPrimaryKey(), 0 ); 1140 } 1141 sTxt.InsertAscii( " XE \"", 0 ); 1142 sTxt.InsertAscii( "\" " ); 1143 break; 1144 1145 case TOX_USER: 1146 ( sTxt.APPEND_CONST_ASC( "\" \\f \"" ) ) 1147 += (sal_Char)( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) ); 1148 // fall through - no break; 1149 case TOX_CONTENT: 1150 { 1151 eType = ww::eTC; 1152 sTxt.InsertAscii( " TC \"", 0 ); 1153 sal_uInt16 nLvl = rAttr.GetLevel(); 1154 if (nLvl > WW8ListManager::nMaxLevel) 1155 nLvl = WW8ListManager::nMaxLevel; 1156 1157 ((sTxt.APPEND_CONST_ASC( "\" \\l " )) 1158 += String::CreateFromInt32( nLvl )) += ' '; 1159 } 1160 break; 1161 default: 1162 ASSERT( !this, "Unhandled option for toc export" ); 1163 break; 1164 } 1165 1166 if ( sTxt.Len() ) 1167 FieldVanish( sTxt, eType ); 1168 } 1169 1170 int WW8SwAttrIter::OutAttrWithRange(xub_StrLen nPos) 1171 { 1172 int nRet = 0; 1173 if ( const SwpHints* pTxtAttrs = rNd.GetpSwpHints() ) 1174 { 1175 m_rExport.m_aCurrentCharPropStarts.push( nPos ); 1176 const xub_StrLen* pEnd; 1177 for ( sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i ) 1178 { 1179 const SwTxtAttr* pHt = (*pTxtAttrs)[i]; 1180 const SfxPoolItem* pItem = &pHt->GetAttr(); 1181 switch ( pItem->Which() ) 1182 { 1183 case RES_TXTATR_INETFMT: 1184 if ( nPos == *pHt->GetStart() ) 1185 { 1186 const SwFmtINetFmt *rINet = static_cast< const SwFmtINetFmt* >( pItem ); 1187 if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) ) 1188 ++nRet; 1189 } 1190 if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd ) 1191 { 1192 if ( m_rExport.AttrOutput().EndURL() ) 1193 --nRet; 1194 } 1195 break; 1196 case RES_TXTATR_REFMARK: 1197 if ( nPos == *pHt->GetStart() ) 1198 { 1199 OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), true ); 1200 ++nRet; 1201 } 1202 if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd ) 1203 { 1204 OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), false ); 1205 --nRet; 1206 } 1207 break; 1208 case RES_TXTATR_TOXMARK: 1209 if ( nPos == *pHt->GetStart() ) 1210 m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) ); 1211 break; 1212 case RES_TXTATR_CJK_RUBY: 1213 if ( nPos == *pHt->GetStart() ) 1214 { 1215 m_rExport.AttrOutput().StartRuby( rNd, *static_cast< const SwFmtRuby* >( pItem ) ); 1216 ++nRet; 1217 } 1218 if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd ) 1219 { 1220 m_rExport.AttrOutput().EndRuby(); 1221 --nRet; 1222 } 1223 break; 1224 } 1225 } 1226 m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem nur in dem obigen Bereich erlaubt 1227 } 1228 return nRet; 1229 } 1230 1231 bool WW8SwAttrIter::IsRedlineAtEnd( xub_StrLen nEnd ) const 1232 { 1233 bool bRet = false; 1234 // search next Redline 1235 for( sal_uInt16 nPos = nCurRedlinePos; 1236 nPos < m_rExport.pDoc->GetRedlineTbl().Count(); ++nPos ) 1237 { 1238 const SwPosition* pEnd = m_rExport.pDoc->GetRedlineTbl()[ nPos ]->End(); 1239 if( pEnd->nNode == rNd ) 1240 { 1241 if( pEnd->nContent.GetIndex() == nEnd ) 1242 { 1243 bRet = true; 1244 break; 1245 } 1246 } 1247 else 1248 break; 1249 } 1250 return bRet; 1251 } 1252 1253 const SwRedlineData* WW8SwAttrIter::GetRedline( xub_StrLen nPos ) 1254 { 1255 if( pCurRedline ) 1256 { 1257 const SwPosition* pEnd = pCurRedline->End(); 1258 if( pEnd->nNode == rNd && 1259 pEnd->nContent.GetIndex() <= nPos ) 1260 { 1261 pCurRedline = 0; 1262 ++nCurRedlinePos; 1263 } 1264 else 1265 { 1266 // write data of current redline 1267 return &( pCurRedline->GetRedlineData() ); 1268 } 1269 } 1270 1271 if( !pCurRedline ) 1272 { 1273 // search next Redline 1274 for( ; nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count(); 1275 ++nCurRedlinePos ) 1276 { 1277 const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nCurRedlinePos ]; 1278 1279 const SwPosition* pStt = pRedl->Start(); 1280 const SwPosition* pEnd = pStt == pRedl->GetPoint() 1281 ? pRedl->GetMark() 1282 : pRedl->GetPoint(); 1283 1284 if( pStt->nNode == rNd ) 1285 { 1286 if( pStt->nContent.GetIndex() >= nPos ) 1287 { 1288 if( pStt->nContent.GetIndex() == nPos ) 1289 { 1290 // write data of this redline 1291 pCurRedline = pRedl; 1292 return &( pCurRedline->GetRedlineData() ); 1293 } 1294 break; 1295 } 1296 } 1297 else 1298 break; 1299 1300 if( pEnd->nNode == rNd && 1301 pEnd->nContent.GetIndex() < nPos ) 1302 { 1303 pCurRedline = pRedl; 1304 break; 1305 } 1306 } 1307 } 1308 return NULL; 1309 } 1310 1311 /* */ 1312 1313 short MSWordExportBase::GetCurrentPageDirection() const 1314 { 1315 const SwFrmFmt &rFmt = pAktPageDesc 1316 ? pAktPageDesc->GetMaster() 1317 : const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 ).GetMaster(); 1318 return rFmt.GetFrmDir().GetValue(); 1319 } 1320 1321 short MSWordExportBase::GetDefaultFrameDirection( ) const 1322 { 1323 short nDir = FRMDIR_ENVIRONMENT; 1324 1325 if ( bOutPageDescs ) 1326 nDir = GetCurrentPageDirection( ); 1327 else if ( pOutFmtNode ) 1328 { 1329 if ( bOutFlyFrmAttrs ) //frame 1330 { 1331 nDir = TrueFrameDirection( *( const SwFrmFmt * ) pOutFmtNode ); 1332 } 1333 else if ( pOutFmtNode->ISA( SwCntntNode ) ) //pagagraph 1334 { 1335 const SwCntntNode *pNd = ( const SwCntntNode * ) pOutFmtNode; 1336 SwPosition aPos( *pNd ); 1337 nDir = pDoc->GetTextDirection( aPos ); 1338 } 1339 else if ( pOutFmtNode->ISA( SwTxtFmtColl ) ) 1340 nDir = FRMDIR_HORI_LEFT_TOP; //what else can we do :-( 1341 } 1342 1343 if ( nDir == FRMDIR_ENVIRONMENT ) 1344 nDir = FRMDIR_HORI_LEFT_TOP; //Set something 1345 1346 return nDir; 1347 } 1348 1349 short MSWordExportBase::TrueFrameDirection( const SwFrmFmt &rFlyFmt ) const 1350 { 1351 const SwFrmFmt *pFlyFmt = &rFlyFmt; 1352 const SvxFrameDirectionItem* pItem = 0; 1353 while ( pFlyFmt ) 1354 { 1355 pItem = &pFlyFmt->GetFrmDir(); 1356 if ( FRMDIR_ENVIRONMENT == pItem->GetValue() ) 1357 { 1358 pItem = 0; 1359 const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor(); 1360 if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) && 1361 pAnchor->GetCntntAnchor() ) 1362 { 1363 pFlyFmt = pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt(); 1364 } 1365 else 1366 pFlyFmt = 0; 1367 } 1368 else 1369 pFlyFmt = 0; 1370 } 1371 1372 short nRet; 1373 if ( pItem ) 1374 nRet = pItem->GetValue(); 1375 else 1376 nRet = GetCurrentPageDirection(); 1377 1378 ASSERT( nRet != FRMDIR_ENVIRONMENT, "leaving with environment direction" ); 1379 return nRet; 1380 } 1381 1382 const SvxBrushItem* WW8Export::GetCurrentPageBgBrush() const 1383 { 1384 const SwFrmFmt &rFmt = pAktPageDesc 1385 ? pAktPageDesc->GetMaster() 1386 : const_cast<const SwDoc *>(pDoc)->GetPageDesc(0).GetMaster(); 1387 1388 const SfxPoolItem* pItem = 0; 1389 //If not set, or "no fill", get real bg 1390 SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true, &pItem); 1391 1392 const SvxBrushItem* pRet = (const SvxBrushItem*)pItem; 1393 if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() && 1394 pRet->GetColor() == COL_TRANSPARENT)) 1395 { 1396 pRet = &(DefaultItemGet<SvxBrushItem>(*pDoc,RES_BACKGROUND)); 1397 } 1398 return pRet; 1399 } 1400 1401 SvxBrushItem WW8Export::TrueFrameBgBrush(const SwFrmFmt &rFlyFmt) const 1402 { 1403 const SwFrmFmt *pFlyFmt = &rFlyFmt; 1404 const SvxBrushItem* pRet = 0; 1405 1406 while (pFlyFmt) 1407 { 1408 //If not set, or "no fill", get real bg 1409 const SfxPoolItem* pItem = 0; 1410 SfxItemState eState = 1411 pFlyFmt->GetItemState(RES_BACKGROUND, true, &pItem); 1412 pRet = (const SvxBrushItem*)pItem; 1413 if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() && 1414 pRet->GetColor() == COL_TRANSPARENT)) 1415 { 1416 pRet = 0; 1417 const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor(); 1418 if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) && 1419 pAnchor->GetCntntAnchor()) 1420 { 1421 pFlyFmt = 1422 pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt(); 1423 } 1424 else 1425 pFlyFmt = 0; 1426 } 1427 else 1428 pFlyFmt = 0; 1429 } 1430 1431 if (!pRet) 1432 pRet = GetCurrentPageBgBrush(); 1433 1434 const Color aTmpColor( COL_WHITE ); 1435 SvxBrushItem aRet( aTmpColor, RES_BACKGROUND ); 1436 if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT))) 1437 aRet = *pRet; 1438 1439 return aRet; 1440 } 1441 1442 1443 /* 1444 Convert characters that need to be converted, the basic replacements and the 1445 ridicously complicated title case attribute mapping to hardcoded upper case 1446 because word doesn't have the feature 1447 */ 1448 String WW8SwAttrIter::GetSnippet(const String &rStr, xub_StrLen nAktPos, 1449 xub_StrLen nLen) const 1450 { 1451 String aSnippet(rStr, nAktPos, nLen); 1452 if (!nLen) 1453 return aSnippet; 1454 1455 // 0x0a ( Hard Line Break ) -> 0x0b 1456 // 0xad ( soft hyphen ) -> 0x1f 1457 // 0x2011 ( hard hyphen ) -> 0x1e 1458 aSnippet.SearchAndReplaceAll(0x0A, 0x0B); 1459 aSnippet.SearchAndReplaceAll(CHAR_HARDHYPHEN, 0x1e); 1460 aSnippet.SearchAndReplaceAll(CHAR_SOFTHYPHEN, 0x1f); 1461 1462 m_rExport.m_aCurrentCharPropStarts.push( nAktPos ); 1463 const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP); 1464 1465 if (SVX_CASEMAP_TITEL == ((const SvxCaseMapItem&)rItem).GetValue()) 1466 { 1467 sal_uInt16 nScriptType = i18n::ScriptType::LATIN; 1468 if (pBreakIt->GetBreakIter().is()) 1469 nScriptType = pBreakIt->GetBreakIter()->getScriptType(aSnippet, 0); 1470 1471 LanguageType nLanguage; 1472 switch (nScriptType) 1473 { 1474 case i18n::ScriptType::ASIAN: 1475 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CJK_LANGUAGE)).GetLanguage(); 1476 break; 1477 case i18n::ScriptType::COMPLEX: 1478 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage(); 1479 break; 1480 case i18n::ScriptType::LATIN: 1481 default: 1482 nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_LANGUAGE)).GetLanguage(); 1483 break; 1484 } 1485 1486 SvxFont aFontHelper; 1487 aFontHelper.SetCaseMap(SVX_CASEMAP_TITEL); 1488 aFontHelper.SetLanguage(nLanguage); 1489 aSnippet = aFontHelper.CalcCaseMap(aSnippet); 1490 1491 //If we weren't at the begin of a word undo the case change. 1492 //not done before doing the casemap because the sequence might start 1493 //with whitespace 1494 if (pBreakIt->GetBreakIter().is() && !pBreakIt->GetBreakIter()->isBeginWord( 1495 rStr, nAktPos, pBreakIt->GetLocale(nLanguage), 1496 i18n::WordType::ANYWORD_IGNOREWHITESPACES ) ) 1497 { 1498 aSnippet.SetChar(0, rStr.GetChar(nAktPos)); 1499 } 1500 } 1501 m_rExport.m_aCurrentCharPropStarts.pop(); 1502 1503 return aSnippet; 1504 } 1505 1506 /** Delivers the right paragraph style 1507 1508 Because of the different style handling for delete operations, 1509 the track changes have to be analysed. A deletion, starting in paragraph A 1510 with style A, ending in paragraph B with style B, needs a hack. 1511 */ 1512 static SwTxtFmtColl& lcl_getFormatCollection( MSWordExportBase& rExport, const SwTxtNode* pTxtNode ) 1513 { 1514 sal_uInt16 nPos = 0; 1515 sal_uInt16 nMax = rExport.pDoc->GetRedlineTbl().Count(); 1516 while( nPos < nMax ) 1517 { 1518 const SwRedline* pRedl = rExport.pDoc->GetRedlineTbl()[ nPos++ ]; 1519 const SwPosition* pStt = pRedl->Start(); 1520 const SwPosition* pEnd = pStt == pRedl->GetPoint() 1521 ? pRedl->GetMark() 1522 : pRedl->GetPoint(); 1523 // Looking for deletions, which ends in current pTxtNode 1524 if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetRedlineData().GetType() && 1525 pEnd->nNode == *pTxtNode && pStt->nNode != *pTxtNode && 1526 pStt->nNode.GetNode().IsTxtNode() ) 1527 { 1528 pTxtNode = pStt->nNode.GetNode().GetTxtNode(); 1529 nMax = nPos; 1530 nPos = 0; 1531 } 1532 } 1533 return static_cast<SwTxtFmtColl&>( pTxtNode->GetAnyFmtColl() ); 1534 } 1535 1536 void WW8AttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop &rSwFmtDrop, sal_uInt16 nStyle, 1537 ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) 1538 { 1539 short nDropLines = rSwFmtDrop.GetLines(); 1540 short nDistance = rSwFmtDrop.GetDistance(); 1541 int rFontHeight, rDropHeight, rDropDescent; 1542 1543 SVBT16 nSty; 1544 ShortToSVBT16( nStyle, nSty ); 1545 m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style # 1546 1547 if ( m_rWW8Export.bWrtWW8 ) 1548 { 1549 m_rWW8Export.InsUInt16( NS_sprm::LN_PPc ); // Alignment (sprmPPc) 1550 m_rWW8Export.pO->Insert( 0x20, m_rWW8Export.pO->Count() ); 1551 1552 m_rWW8Export.InsUInt16( NS_sprm::LN_PWr ); // Wrapping (sprmPWr) 1553 m_rWW8Export.pO->Insert( 0x02, m_rWW8Export.pO->Count() ); 1554 1555 m_rWW8Export.InsUInt16( NS_sprm::LN_PDcs ); // Dropcap (sprmPDcs) 1556 int nDCS = ( nDropLines << 3 ) | 0x01; 1557 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) ); 1558 1559 m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText ); // Distance from text (sprmPDxaFromText) 1560 m_rWW8Export.InsUInt16( nDistance ); 1561 1562 if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) ) 1563 { 1564 m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaLine ); // Line spacing 1565 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) ); 1566 m_rWW8Export.InsUInt16( 0 ); 1567 } 1568 } 1569 else 1570 { 1571 m_rWW8Export.pO->Insert( 29, m_rWW8Export.pO->Count() ); // Alignment (sprmPPc) 1572 m_rWW8Export.pO->Insert( 0x20, m_rWW8Export.pO->Count() ); 1573 1574 m_rWW8Export.pO->Insert( 37, m_rWW8Export.pO->Count() ); // Wrapping (sprmPWr) 1575 m_rWW8Export.pO->Insert( 0x02, m_rWW8Export.pO->Count() ); 1576 1577 m_rWW8Export.pO->Insert( 46, m_rWW8Export.pO->Count() ); // Dropcap (sprmPDcs) 1578 int nDCS = ( nDropLines << 3 ) | 0x01; 1579 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) ); 1580 1581 m_rWW8Export.pO->Insert( 49, m_rWW8Export.pO->Count() ); // Distance from text (sprmPDxaFromText) 1582 m_rWW8Export.InsUInt16( nDistance ); 1583 1584 if (rNode.GetDropSize(rFontHeight, rDropHeight, rDropDescent)) 1585 { 1586 m_rWW8Export.pO->Insert( 20, m_rWW8Export.pO->Count() ); // Line spacing 1587 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) ); 1588 m_rWW8Export.InsUInt16( 0 ); 1589 } 1590 } 1591 1592 m_rWW8Export.WriteCR( pTextNodeInfoInner ); 1593 1594 if ( pTextNodeInfo.get() != NULL ) 1595 { 1596 #ifdef DEBUG 1597 ::std::clog << pTextNodeInfo->toString() << ::std::endl; 1598 #endif 1599 1600 TableInfoCell( pTextNodeInfoInner ); 1601 } 1602 1603 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() ); 1604 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); 1605 1606 if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) ) 1607 { 1608 if ( m_rWW8Export.bWrtWW8 ) 1609 { 1610 const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt(); 1611 if ( pSwCharFmt ) 1612 { 1613 m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd ); 1614 m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) ); 1615 } 1616 1617 m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsPos ); // Lower the chars 1618 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) ); 1619 1620 m_rWW8Export.InsUInt16( NS_sprm::LN_CHps ); // Font Size 1621 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) ); 1622 } 1623 else 1624 { 1625 const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt(); 1626 if ( pSwCharFmt ) 1627 { 1628 m_rWW8Export.InsUInt16( 80 ); 1629 m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) ); 1630 } 1631 1632 m_rWW8Export.pO->Insert( 101, m_rWW8Export.pO->Count() ); // Lower the chars 1633 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) ); 1634 1635 m_rWW8Export.pO->Insert( 99, m_rWW8Export.pO->Count() ); // Font Size 1636 m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) ); 1637 } 1638 } 1639 1640 m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() ); 1641 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); 1642 } 1643 1644 xub_StrLen MSWordExportBase::GetNextPos( WW8SwAttrIter* aAttrIter, const SwTxtNode& rNode, xub_StrLen nAktPos ) 1645 { 1646 // Get the bookmarks for the normal run 1647 xub_StrLen nNextPos = aAttrIter->WhereNext(); 1648 xub_StrLen nNextBookmark = nNextPos; 1649 1650 if( nNextBookmark > nAktPos )//no need to search for bookmarks otherwise 1651 { 1652 GetSortedBookmarks( rNode, nAktPos, nNextBookmark - nAktPos ); 1653 NearestBookmark( nNextBookmark, nAktPos, false ); 1654 } 1655 return std::min( nNextPos, nNextBookmark ); 1656 } 1657 1658 void MSWordExportBase::UpdatePosition( WW8SwAttrIter* aAttrIter, xub_StrLen nAktPos, xub_StrLen /*nEnd*/ ) 1659 { 1660 xub_StrLen nNextPos; 1661 1662 // go to next attribute if no bookmark is found and if the next attribute position if at the current position 1663 bool bNextBookmark = NearestBookmark( nNextPos, nAktPos, true ); 1664 if( !bNextBookmark && nAktPos >= aAttrIter->WhereNext() ) 1665 aAttrIter->NextPos(); 1666 } 1667 1668 bool MSWordExportBase::GetBookmarks( const SwTxtNode& rNd, xub_StrLen nStt, 1669 xub_StrLen nEnd, IMarkVector& rArr ) 1670 { 1671 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1672 sal_uLong nNd = rNd.GetIndex( ); 1673 1674 const sal_Int32 nMarks = pMarkAccess->getMarksCount(); 1675 for ( sal_Int32 i = 0; i < nMarks; i++ ) 1676 { 1677 IMark* pMark = ( pMarkAccess->getMarksBegin() + i )->get(); 1678 1679 // Only keep the bookmarks starting or ending in this node 1680 if ( pMark->GetMarkStart().nNode == nNd || 1681 pMark->GetMarkEnd().nNode == nNd ) 1682 { 1683 xub_StrLen nBStart = pMark->GetMarkStart().nContent.GetIndex(); 1684 xub_StrLen nBEnd = pMark->GetMarkEnd().nContent.GetIndex(); 1685 1686 // Keep only the bookmars starting or ending in the snippet 1687 bool bIsStartOk = ( nBStart >= nStt ) && ( nBStart <= nEnd ); 1688 bool bIsEndOk = ( nBEnd >= nStt ) && ( nBEnd <= nEnd ); 1689 1690 if ( bIsStartOk || bIsEndOk ) 1691 rArr.push_back( pMark ); 1692 } 1693 } 1694 return ( rArr.size() > 0 ); 1695 } 1696 1697 class CompareMarksEnd : public std::binary_function < const IMark *, const IMark *, bool > 1698 { 1699 public: 1700 inline bool operator() ( const IMark * pOneB, const IMark * pTwoB ) const 1701 { 1702 xub_StrLen nOEnd = pOneB->GetMarkEnd().nContent.GetIndex(); 1703 xub_StrLen nTEnd = pTwoB->GetMarkEnd().nContent.GetIndex(); 1704 1705 return nOEnd < nTEnd; 1706 } 1707 }; 1708 1709 bool MSWordExportBase::NearestBookmark( xub_StrLen& rNearest, const xub_StrLen nAktPos, bool bNextPositionOnly ) 1710 { 1711 bool bHasBookmark = false; 1712 1713 if ( m_rSortedMarksStart.size( ) > 0 ) 1714 { 1715 IMark* pMarkStart = m_rSortedMarksStart.front(); 1716 xub_StrLen nNext = pMarkStart->GetMarkStart().nContent.GetIndex(); 1717 if( !bNextPositionOnly || (nNext > nAktPos )) 1718 { 1719 rNearest = nNext; 1720 bHasBookmark = true; 1721 } 1722 } 1723 1724 if ( m_rSortedMarksEnd.size( ) > 0 ) 1725 { 1726 IMark* pMarkEnd = m_rSortedMarksEnd[0]; 1727 xub_StrLen nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex(); 1728 if( !bNextPositionOnly || nNext > nAktPos ) 1729 { 1730 if ( !bHasBookmark ) 1731 rNearest = nNext; 1732 else 1733 rNearest = std::min( rNearest, nNext ); 1734 bHasBookmark = true; 1735 } 1736 } 1737 1738 return bHasBookmark; 1739 } 1740 1741 void MSWordExportBase::GetSortedBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen ) 1742 { 1743 IMarkVector aMarksStart; 1744 if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarksStart ) ) 1745 { 1746 IMarkVector aSortedEnd; 1747 IMarkVector aSortedStart; 1748 for ( IMarkVector::const_iterator it = aMarksStart.begin(), end = aMarksStart.end(); 1749 it < end; ++it ) 1750 { 1751 IMark* pMark = (*it); 1752 1753 // Remove the positions egals to the current pos 1754 xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex(); 1755 xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex(); 1756 1757 if ( nStart > nAktPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) ) 1758 aSortedStart.push_back( pMark ); 1759 1760 if ( nEnd > nAktPos && nEnd <= ( nAktPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) ) 1761 aSortedEnd.push_back( pMark ); 1762 } 1763 1764 // Sort the bookmarks by end position 1765 std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() ); 1766 1767 m_rSortedMarksStart.swap( aSortedStart ); 1768 m_rSortedMarksEnd.swap( aSortedEnd ); 1769 } 1770 else 1771 { 1772 m_rSortedMarksStart.clear( ); 1773 m_rSortedMarksEnd.clear( ); 1774 } 1775 } 1776 1777 void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode ) 1778 { 1779 #ifdef DEBUG 1780 ::std::clog << "<OutWW8_SwTxtNode>" << ::std::endl; 1781 #endif 1782 1783 ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( mpTableInfo->getTableNodeInfo( &rNode ) ); 1784 1785 AttrOutput().StartParagraph( pTextNodeInfo ); 1786 1787 bool bFlyInTable = mpParentFrame && IsInTable(); 1788 1789 if ( !bFlyInTable ) 1790 nStyleBeforeFly = GetId( lcl_getFormatCollection( *this, &rNode ) ); 1791 1792 // nStyleBeforeFly may change when we recurse into another node, so we 1793 // have to remember it in nStyle 1794 sal_uInt16 nStyle = nStyleBeforeFly; 1795 1796 WW8SwAttrIter aAttrIter( *this, rNode ); 1797 rtl_TextEncoding eChrSet = aAttrIter.GetCharSet(); 1798 1799 if ( bStartTOX ) 1800 { 1801 // ignore TOX header section 1802 const SwSectionNode* pSectNd = rNode.FindSectionNode(); 1803 if ( pSectNd && TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() ) 1804 { 1805 AttrOutput().StartTOX( pSectNd->GetSection() ); 1806 m_aCurrentCharPropStarts.push( 0 ); 1807 } 1808 } 1809 1810 const SwSection* pTOXSect = 0; 1811 if( bInWriteTOX ) 1812 { 1813 // check for end of TOX 1814 SwNodeIndex aIdx( rNode, 1 ); 1815 if( !aIdx.GetNode().IsTxtNode() ) 1816 { 1817 const SwSectionNode* pTOXSectNd = rNode.FindSectionNode(); 1818 pTOXSect = &pTOXSectNd->GetSection(); 1819 1820 const SwNode* pNxt = rNode.GetNodes().GoNext( &aIdx ); 1821 if( pNxt && pNxt->FindSectionNode() == pTOXSectNd ) 1822 pTOXSect = 0; 1823 } 1824 } 1825 1826 if ( aAttrIter.RequiresImplicitBookmark() ) 1827 { 1828 String sBkmkName = String( RTL_CONSTASCII_STRINGPARAM( "_toc" ) ); 1829 sBkmkName += String::CreateFromInt32( rNode.GetIndex() ); 1830 AppendWordBookmark( sBkmkName ); 1831 } 1832 1833 //Would need to move into WW8Export, probably not worth it 1834 //ASSERT( pO->Count(), " pO ist am Zeilenanfang nicht leer" ); 1835 1836 String aStr( rNode.GetTxt() ); 1837 1838 xub_StrLen nAktPos = 0; 1839 xub_StrLen const nEnd = aStr.Len(); 1840 bool bRedlineAtEnd = false; 1841 int nOpenAttrWithRange = 0; 1842 1843 ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner; 1844 if ( pTextNodeInfo.get() != NULL ) 1845 pTextNodeInfoInner = pTextNodeInfo->getFirstInner(); 1846 1847 do { 1848 const SwRedlineData* pRedlineData = aAttrIter.GetRedline( nAktPos ); 1849 1850 AttrOutput().StartRun( pRedlineData ); 1851 1852 xub_StrLen nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos ); 1853 1854 if( nNextAttr > nEnd ) 1855 nNextAttr = nEnd; 1856 1857 aAttrIter.OutFlys( nAktPos ); 1858 //Append bookmarks in this range after flys, exclusive of final 1859 //position of this range 1860 AppendBookmarks( rNode, nAktPos, nNextAttr - nAktPos ); 1861 bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos ); 1862 nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nAktPos); 1863 1864 xub_StrLen nLen = nNextAttr - nAktPos; 1865 if ( !bTxtAtr && nLen ) 1866 { 1867 sal_Unicode ch = aStr.GetChar( nAktPos ); 1868 int ofs = ( ch == CH_TXT_ATR_FIELDSTART || ch == CH_TXT_ATR_FIELDEND || ch == CH_TXT_ATR_FORMELEMENT? 1: 0 ); 1869 1870 IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess(); 1871 if ( ch == CH_TXT_ATR_FIELDSTART ) 1872 { 1873 SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos + 1 ) ); 1874 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition ); 1875 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" ); 1876 1877 if ( pFieldmark->GetFieldname().equalsAscii( ODF_FORMTEXT ) ) 1878 AppendBookmark( pFieldmark->GetName(), false ); 1879 OutputField( NULL, lcl_getFieldId( pFieldmark ), lcl_getFieldCode( pFieldmark ), WRITEFIELD_START | WRITEFIELD_CMD_START ); 1880 if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMTEXT ) ) 1881 WriteFormData( *pFieldmark ); 1882 else if ( pFieldmark->GetFieldname( ).equalsAscii( ODF_HYPERLINK ) ) 1883 WriteHyperlinkData( *pFieldmark ); 1884 OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CMD_END ); 1885 } 1886 else if ( ch == CH_TXT_ATR_FIELDEND ) 1887 { 1888 SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) ); 1889 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition ); 1890 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" ); 1891 1892 OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CLOSE ); 1893 if ( pFieldmark->GetFieldname().equalsAscii( ODF_FORMTEXT ) ) 1894 AppendBookmark( pFieldmark->GetName(), false ); 1895 } 1896 else if ( ch == CH_TXT_ATR_FORMELEMENT ) 1897 { 1898 SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) ); 1899 ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition ); 1900 OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" ); 1901 1902 bool isDropdownOrCheckbox = pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMDROPDOWN ) || 1903 pFieldmark->GetFieldname( ).equalsAscii( ODF_FORMCHECKBOX ); 1904 1905 if ( isDropdownOrCheckbox ) 1906 AppendBookmark( pFieldmark->GetName(), 0 ); 1907 OutputField( NULL, lcl_getFieldId( pFieldmark ), 1908 lcl_getFieldCode( pFieldmark ), 1909 WRITEFIELD_START | WRITEFIELD_CMD_START ); 1910 if ( isDropdownOrCheckbox ) 1911 WriteFormData( *pFieldmark ); 1912 OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CLOSE ); 1913 if ( isDropdownOrCheckbox ) 1914 AppendBookmark( pFieldmark->GetName(), false ); 1915 } 1916 nLen -= static_cast< sal_uInt16 >( ofs ); 1917 1918 String aSnippet( aAttrIter.GetSnippet( aStr, nAktPos + static_cast< sal_uInt16 >( ofs ), nLen ) ); 1919 if ( ( nTxtTyp == TXT_EDN || nTxtTyp == TXT_FTN ) && nAktPos == 0 && nLen > 0 ) 1920 { 1921 // Insert tab for aesthetic puposes #i24762# 1922 if ( aSnippet.GetChar( 0 ) != 0x09 ) 1923 aSnippet.Insert( 0x09, 0 ); 1924 } 1925 AttrOutput().RunText( aSnippet, eChrSet ); 1926 } 1927 1928 if ( aAttrIter.IsDropCap( nNextAttr ) ) 1929 AttrOutput().FormatDrop( rNode, aAttrIter.GetSwFmtDrop(), nStyle, pTextNodeInfo, pTextNodeInfoInner ); 1930 1931 if (0 != nEnd) 1932 { 1933 // Output the character attributes 1934 // #i51277# do this before writing flys at end of paragraph 1935 AttrOutput().StartRunProperties(); 1936 aAttrIter.OutAttr( nAktPos ); 1937 AttrOutput().EndRunProperties( pRedlineData ); 1938 } 1939 1940 // At the end of line, output the attributes until the CR. 1941 // Exception: footnotes at the end of line 1942 if ( nNextAttr == nEnd ) 1943 { 1944 ASSERT( nOpenAttrWithRange >= 0, "odd to see this happening, expected >= 0" ); 1945 if ( !bTxtAtr && nOpenAttrWithRange <= 0 ) 1946 { 1947 if ( aAttrIter.IsRedlineAtEnd( nEnd ) ) 1948 bRedlineAtEnd = true; 1949 else 1950 { 1951 // insert final graphic anchors if any before CR 1952 aAttrIter.OutFlys( nEnd ); 1953 // insert final bookmarks if any before CR and after flys 1954 AppendBookmarks( rNode, nEnd, 1 ); 1955 if ( pTOXSect ) 1956 { 1957 m_aCurrentCharPropStarts.pop(); 1958 AttrOutput().EndTOX( *pTOXSect ,false); 1959 } 1960 WriteCR( pTextNodeInfoInner ); 1961 } 1962 } 1963 } 1964 1965 if (0 == nEnd) 1966 { 1967 // Output the character attributes 1968 // do it after WriteCR for an empty paragraph (otherwise 1969 // WW8_WrFkp::Append throws SPRMs away...) 1970 AttrOutput().StartRunProperties(); 1971 aAttrIter.OutAttr( nAktPos ); 1972 AttrOutput().EndRunProperties( pRedlineData ); 1973 } 1974 1975 // Exception: footnotes at the end of line 1976 if ( nNextAttr == nEnd ) 1977 { 1978 ASSERT(nOpenAttrWithRange >= 0, 1979 "odd to see this happening, expected >= 0"); 1980 bool bAttrWithRange = (nOpenAttrWithRange > 0); 1981 if ( nAktPos != nEnd ) 1982 { 1983 nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nEnd); 1984 ASSERT(nOpenAttrWithRange == 0, 1985 "odd to see this happening, expected 0"); 1986 } 1987 1988 AttrOutput().OutputFKP(); 1989 1990 if ( bTxtAtr || bAttrWithRange || bRedlineAtEnd ) 1991 { 1992 // insert final graphic anchors if any before CR 1993 aAttrIter.OutFlys( nEnd ); 1994 // insert final bookmarks if any before CR and after flys 1995 AppendBookmarks( rNode, nEnd, 1 ); 1996 WriteCR( pTextNodeInfoInner ); 1997 1998 if ( pTOXSect ) 1999 { 2000 m_aCurrentCharPropStarts.pop(); 2001 AttrOutput().EndTOX( *pTOXSect ); 2002 } 2003 2004 if ( bRedlineAtEnd ) 2005 { 2006 AttrOutput().Redline( aAttrIter.GetRedline( nEnd ) ); 2007 AttrOutput().OutputFKP(); 2008 } 2009 } 2010 } 2011 2012 AttrOutput().EndRun(); 2013 2014 nAktPos = nNextAttr; 2015 UpdatePosition( &aAttrIter, nAktPos, nEnd ); 2016 eChrSet = aAttrIter.GetCharSet(); 2017 } 2018 while ( nAktPos < nEnd ); 2019 2020 AttrOutput().StartParagraphProperties( rNode ); 2021 2022 AttrOutput().ParagraphStyle( nStyle ); 2023 2024 if ( mpParentFrame && IsInTable() ) // Fly-Attrs 2025 OutputFormat( mpParentFrame->GetFrmFmt(), false, false, true ); 2026 2027 if ( pTextNodeInfo.get() != NULL ) 2028 { 2029 #ifdef DEBUG 2030 ::std::clog << pTextNodeInfo->toString() << ::std::endl; 2031 #endif 2032 2033 AttrOutput().TableInfoCell( pTextNodeInfoInner ); 2034 if (pTextNodeInfoInner->isFirstInTable()) 2035 { 2036 const SwTable * pTable = pTextNodeInfoInner->getTable(); 2037 2038 const SwTableFmt * pTabFmt = pTable->GetTableFmt(); 2039 if (pTabFmt != NULL) 2040 { 2041 if (pTabFmt->GetBreak().GetBreak() == SVX_BREAK_PAGE_BEFORE) 2042 AttrOutput().PageBreakBefore(true); 2043 } 2044 } 2045 } 2046 2047 if ( !bFlyInTable ) 2048 { 2049 SfxItemSet* pTmpSet = 0; 2050 const sal_uInt8 nPrvNxtNd = rNode.HasPrevNextLayNode(); 2051 2052 if( (ND_HAS_PREV_LAYNODE|ND_HAS_NEXT_LAYNODE ) != nPrvNxtNd ) 2053 { 2054 const SfxPoolItem* pItem; 2055 if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState( 2056 RES_UL_SPACE, true, &pItem ) && 2057 ( ( !( ND_HAS_PREV_LAYNODE & nPrvNxtNd ) && 2058 ((SvxULSpaceItem*)pItem)->GetUpper()) || 2059 ( !( ND_HAS_NEXT_LAYNODE & nPrvNxtNd ) && 2060 ((SvxULSpaceItem*)pItem)->GetLower()) )) 2061 { 2062 pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() ); 2063 SvxULSpaceItem aUL( *(SvxULSpaceItem*)pItem ); 2064 // OD, MMAHER 2004-03-01 #i25901#- consider compatibility option 2065 if (!pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES)) 2066 { 2067 if( !(ND_HAS_PREV_LAYNODE & nPrvNxtNd )) 2068 aUL.SetUpper( 0 ); 2069 } 2070 // OD, MMAHER 2004-03-01 #i25901# - consider compatibility option 2071 if (!pDoc->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS)) 2072 { 2073 if( !(ND_HAS_NEXT_LAYNODE & nPrvNxtNd )) 2074 aUL.SetLower( 0 ); 2075 } 2076 pTmpSet->Put( aUL ); 2077 } 2078 } 2079 2080 sal_Bool bParaRTL = sal_False; 2081 const SvxFrameDirectionItem* pItem = (const SvxFrameDirectionItem*) 2082 rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR); 2083 if ( aAttrIter.IsParaRTL()) 2084 bParaRTL = sal_True; 2085 2086 if( rNode.IsNumbered()) 2087 { 2088 const SwNumRule* pRule = rNode.GetNumRule(); 2089 sal_uInt8 nLvl = static_cast< sal_uInt8 >( rNode.GetActualListLevel() ); 2090 const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl ); 2091 if( !pFmt ) 2092 pFmt = &pRule->Get( nLvl ); 2093 2094 if( !pTmpSet ) 2095 pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() ); 2096 2097 SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*pTmpSet, RES_LR_SPACE)); 2098 // --> OD 2008-06-03 #i86652# 2099 if ( pFmt->GetPositionAndSpaceMode() == 2100 SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2101 { 2102 aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetAbsLSpace() ); 2103 } 2104 // <-- 2105 2106 if( rNode.IsNumbered() && rNode.IsCountedInList() ) 2107 { 2108 // --> OD 2008-06-03 #i86652# 2109 if ( pFmt->GetPositionAndSpaceMode() == 2110 SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2111 { 2112 if (bParaRTL) 2113 aLR.SetTxtFirstLineOfstValue(pFmt->GetAbsLSpace() - pFmt->GetFirstLineOffset()); 2114 else 2115 aLR.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt)); 2116 } 2117 // <-- 2118 2119 // --> OD 2009-03-09 #100020# 2120 // correct fix for issue i94187 2121 if (SFX_ITEM_SET != 2122 pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) ) 2123 { 2124 // List style set via paragraph style - then put it into the itemset. 2125 // This is needed to get list level and list id exported for 2126 // the paragraph. 2127 pTmpSet->Put( SwNumRuleItem( pRule->GetName() )); 2128 2129 // Put indent values into the itemset in case that the list 2130 // style is applied via paragraph style and the list level 2131 // indent values are not applicable. 2132 if ( pFmt->GetPositionAndSpaceMode() == 2133 SvxNumberFormat::LABEL_ALIGNMENT && 2134 !rNode.AreListLevelIndentsApplicable() ) 2135 { 2136 pTmpSet->Put( aLR ); 2137 } 2138 } 2139 } 2140 else 2141 pTmpSet->ClearItem(RES_PARATR_NUMRULE); 2142 2143 // --> OD 2008-06-03 #i86652# 2144 if ( pFmt->GetPositionAndSpaceMode() == 2145 SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2146 { 2147 pTmpSet->Put(aLR); 2148 2149 //#i21847# 2150 SvxTabStopItem aItem( 2151 ItemGet<SvxTabStopItem>(*pTmpSet, RES_PARATR_TABSTOP)); 2152 SvxTabStop aTabStop(pFmt->GetAbsLSpace()); 2153 aItem.Insert(aTabStop); 2154 pTmpSet->Put(aItem); 2155 2156 MSWordExportBase::CorrectTabStopInSet(*pTmpSet, pFmt->GetAbsLSpace()); 2157 } 2158 } 2159 2160 /* 2161 If a given para is using the FRMDIR_ENVIRONMENT direction we 2162 cannot export that, its its ltr then that's ok as thats word's 2163 default. Otherwise we must add a RTL attribute to our export list 2164 */ 2165 pItem = (const SvxFrameDirectionItem*) 2166 rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR); 2167 if ( 2168 (!pItem || pItem->GetValue() == FRMDIR_ENVIRONMENT) && 2169 aAttrIter.IsParaRTL() 2170 ) 2171 { 2172 if ( !pTmpSet ) 2173 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet()); 2174 2175 pTmpSet->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP, RES_FRAMEDIR)); 2176 } 2177 // --> OD 2005-10-18 #126238# - move code for handling of numbered, 2178 // but not counted paragraphs to this place. Otherwise, the paragraph 2179 // isn't exported as numbered, but not counted, if no other attribute 2180 // is found in <pTmpSet> 2181 // #i44815# adjust numbering/indents for numbered paragraphs 2182 // without number (NO_NUMLEVEL) 2183 // #i47013# need to check rNode.GetNumRule()!=NULL as well. 2184 if ( ! rNode.IsCountedInList() && rNode.GetNumRule()!=NULL ) 2185 { 2186 // WW8 does not know numbered paragraphs without number 2187 // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export 2188 // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means 2189 // no numbering. Here, we will adjust the indents to match 2190 // visually. 2191 2192 if ( !pTmpSet ) 2193 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet()); 2194 2195 // create new LRSpace item, based on the current (if present) 2196 const SfxPoolItem* pPoolItem = NULL; 2197 pTmpSet->GetItemState(RES_LR_SPACE, sal_True, &pPoolItem); 2198 SvxLRSpaceItem aLRSpace( 2199 ( pPoolItem == NULL ) 2200 ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE) 2201 : *static_cast<const SvxLRSpaceItem*>( pPoolItem ) ); 2202 2203 // new left margin = old left + label space 2204 const SwNumRule* pRule = rNode.GetNumRule(); 2205 const SwNumFmt& rNumFmt = pRule->Get( static_cast< sal_uInt16 >(rNode.GetActualListLevel()) ); 2206 // --> OD 2008-06-03 #i86652# 2207 if ( rNumFmt.GetPositionAndSpaceMode() == 2208 SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) 2209 { 2210 aLRSpace.SetTxtLeft( aLRSpace.GetLeft() + rNumFmt.GetAbsLSpace() ); 2211 2212 // new first line indent = 0 2213 // (first line indent is ignored for NO_NUMLEVEL) 2214 if (!bParaRTL) 2215 aLRSpace.SetTxtFirstLineOfst( 0 ); 2216 2217 // put back the new item 2218 pTmpSet->Put( aLRSpace ); 2219 } 2220 // <-- 2221 2222 // assure that numbering rule is in <pTmpSet> 2223 if (SFX_ITEM_SET != pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) ) 2224 { 2225 pTmpSet->Put( SwNumRuleItem( pRule->GetName() )); 2226 } 2227 } 2228 2229 // --> OD 2007-04-24 #i75457# 2230 // Export page break after attribute from paragraph style. 2231 // If page break attribute at the text node exist, an existing page 2232 // break after at the paragraph style hasn't got to be considered. 2233 if ( !rNode.GetpSwAttrSet() || 2234 SFX_ITEM_SET != rNode.GetpSwAttrSet()->GetItemState(RES_BREAK, false) ) 2235 { 2236 const SvxFmtBreakItem* pBreakAtParaStyle = 2237 &(ItemGet<SvxFmtBreakItem>(rNode.GetSwAttrSet(), RES_BREAK)); 2238 if ( pBreakAtParaStyle && 2239 pBreakAtParaStyle->GetBreak() == SVX_BREAK_PAGE_AFTER ) 2240 { 2241 if ( !pTmpSet ) 2242 { 2243 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet()); 2244 } 2245 pTmpSet->Put( *pBreakAtParaStyle ); 2246 } 2247 else if( pTmpSet ) 2248 { // Even a pagedesc item is set, the break item can be set 'NONE', 2249 // this has to be overruled. 2250 const SwFmtPageDesc& rPageDescAtParaStyle = 2251 ItemGet<SwFmtPageDesc>( rNode, RES_PAGEDESC ); 2252 if( rPageDescAtParaStyle.KnowsPageDesc() ) 2253 pTmpSet->ClearItem( RES_BREAK ); 2254 } 2255 } 2256 2257 // --> FME 2007-05-30 #i76520# Emulate non-splitting tables 2258 if ( bOutTable ) 2259 { 2260 const SwTableNode* pTableNode = rNode.FindTableNode(); 2261 2262 if ( pTableNode ) 2263 { 2264 const SwTable& rTable = pTableNode->GetTable(); 2265 const SvxFmtKeepItem& rKeep = rTable.GetFrmFmt()->GetKeep(); 2266 const bool bKeep = rKeep.GetValue(); 2267 const bool bDontSplit = !bKeep ? 2268 !rTable.GetFrmFmt()->GetLayoutSplit().GetValue() : 2269 false; 2270 2271 if ( bKeep || bDontSplit ) 2272 { 2273 // bKeep: set keep at first paragraphs in all lines 2274 // bDontSplit : set keep at first paragraphs in all lines except from last line 2275 // but only for non-complex tables 2276 const SwTableBox* pBox = rNode.GetTblBox(); 2277 const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0; 2278 2279 if ( pLine && !pLine->GetUpper() ) 2280 { 2281 // check if box is first in that line: 2282 if ( 0 == pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() ) 2283 { 2284 // check if paragraph is first in that line: 2285 if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) ) 2286 { 2287 bool bSetAtPara = false; 2288 if ( bKeep ) 2289 bSetAtPara = true; 2290 else if ( bDontSplit ) 2291 { 2292 // check if pLine isn't last line in table 2293 if ( rTable.GetTabLines().Count() - rTable.GetTabLines().GetPos( pLine ) != 1 ) 2294 bSetAtPara = true; 2295 } 2296 2297 if ( bSetAtPara ) 2298 { 2299 if ( !pTmpSet ) 2300 pTmpSet = new SfxItemSet(rNode.GetSwAttrSet()); 2301 2302 const SvxFmtKeepItem aKeepItem( sal_True, RES_KEEP ); 2303 pTmpSet->Put( aKeepItem ); 2304 } 2305 } 2306 } 2307 } 2308 } 2309 } 2310 } 2311 // <-- 2312 2313 const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet(); 2314 if( pNewSet ) 2315 { // Para-Attrs 2316 pStyAttr = &rNode.GetAnyFmtColl().GetAttrSet(); 2317 2318 const SwModify* pOldMod = pOutFmtNode; 2319 pOutFmtNode = &rNode; 2320 2321 // Pap-Attrs, so script is not necessary 2322 OutputItemSet( *pNewSet, true, false, i18n::ScriptType::LATIN, false); 2323 2324 pStyAttr = 0; 2325 pOutFmtNode = pOldMod; 2326 2327 if( pNewSet != rNode.GetpSwAttrSet() ) 2328 delete pNewSet; 2329 } 2330 } 2331 2332 AttrOutput().EndParagraphProperties(); 2333 2334 AttrOutput().EndParagraph( pTextNodeInfoInner ); 2335 2336 #ifdef DEBUG 2337 ::std::clog << "</OutWW8_SwTxtNode>" << ::std::endl; 2338 #endif 2339 } 2340 2341 void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo ) 2342 { 2343 SVBT16 nSty; 2344 ShortToSVBT16( GetExport().nStyleBeforeFly, nSty ); 2345 2346 ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt( pNodeInfo->getInners().begin() ); 2347 ww8::WW8TableNodeInfo::Inners_t::const_iterator aItEnd( pNodeInfo->getInners().end() ); 2348 2349 while (aIt != aItEnd) 2350 { 2351 ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second; 2352 if ( pInner->isEndOfCell() ) 2353 { 2354 TableRowEnd( pInner->getDepth() ); 2355 2356 m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style # 2357 TableInfoRow( pInner ); 2358 m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), 2359 m_rWW8Export.pO->GetData() ); 2360 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren 2361 } 2362 2363 if ( pInner->isEndOfLine() ) 2364 { 2365 } 2366 2367 aIt++; 2368 } 2369 } 2370 2371 #if 0 2372 /* */ 2373 2374 sal_uInt16 WW8Export::StartTableFromFrmFmt( WW8Bytes &rAt, const SwFrmFmt *pFmt ) 2375 { 2376 // Tell the undocumented table hack that everything between here and 2377 // the last table position is nontable text 2378 if ( WW8_CP nPos = Fc2Cp( Strm().Tell() ) ) 2379 pMagicTable->Append(nPos,0); 2380 2381 // sprmPDxaFromText10 2382 if( bWrtWW8 ) 2383 { 2384 static sal_uInt8 __READONLY_DATA aTabLineAttr[] = { 2385 0, 0, // Sty # 0 2386 0x16, 0x24, 1, // sprmPFInTable 2387 0x17, 0x24, 1 }; // sprmPFTtp 2388 rAt.Insert( aTabLineAttr, sizeof( aTabLineAttr ), rAt.Count() ); 2389 } 2390 else 2391 { 2392 static sal_uInt8 __READONLY_DATA aTabLineAttr[] = { 2393 0, 0, // Sty # 0 2394 24, 1, // sprmPFInTable 2395 25, 1 }; // sprmPFTtp 2396 rAt.Insert( aTabLineAttr, sizeof( aTabLineAttr ), rAt.Count() ); 2397 } 2398 2399 ASSERT( pFmt, "No pFmt!" ); 2400 if ( pFmt ) 2401 { 2402 const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient(); 2403 const SwFmtVertOrient &rVert = pFmt->GetVertOrient(); 2404 if ( 2405 (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() || 2406 text::RelOrientation::FRAME == rHori.GetRelationOrient()) 2407 && 2408 (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() || 2409 text::RelOrientation::FRAME == rVert.GetRelationOrient()) 2410 ) 2411 { 2412 sal_Int16 eHOri = rHori.GetHoriOrient(); 2413 switch (eHOri) 2414 { 2415 case text::HoriOrientation::CENTER: 2416 case text::HoriOrientation::RIGHT: 2417 if( bWrtWW8 ) 2418 SwWW8Writer::InsUInt16( rAt, NS_sprm::LN_TJc ); 2419 else 2420 rAt.Insert( 182, rAt.Count() ); 2421 SwWW8Writer::InsUInt16( rAt, (text::HoriOrientation::RIGHT == eHOri ? 2 : 1 )); 2422 break; 2423 default: 2424 break; 2425 } 2426 } 2427 } 2428 return rAt.Count(); 2429 } 2430 2431 //See #i19484# for why we need this 2432 static bool CellContainsProblematicGraphic( const SwWriteTableCell *pCell, 2433 const MSWordExportBase &rExport ) 2434 { 2435 const SwNode *pStart = pCell ? pCell->GetBox()->GetSttNd() : 0; 2436 const SwNode *pEnd = pStart ? pStart->EndOfSectionNode() : 0; 2437 ASSERT( pStart && pEnd, "No start or end?" ); 2438 if ( !pStart || !pEnd ) 2439 return false; 2440 2441 bool bHasGraphic = false; 2442 2443 sw::Frames aFrames( GetFramesBetweenNodes( rExport.maFrames, *pStart, *pEnd ) ); 2444 sw::FrameIter aEnd = aFrames.end(); 2445 for ( sw::FrameIter aIter = aFrames.begin(); aIter != aEnd; ++aIter ) 2446 { 2447 const SwFrmFmt &rEntry = aIter->GetFrmFmt(); 2448 if ( rEntry.GetSurround().GetSurround() == SURROUND_THROUGHT ) 2449 { 2450 bHasGraphic = true; 2451 break; 2452 } 2453 } 2454 return bHasGraphic; 2455 } 2456 2457 static bool RowContainsProblematicGraphic( const SwWriteTableCellPtr *pRow, 2458 sal_uInt16 nCols, const MSWordExportBase &rExport ) 2459 { 2460 bool bHasGraphic = false; 2461 for ( sal_uInt16 nI = 0; nI < nCols; ++nI ) 2462 { 2463 if ( CellContainsProblematicGraphic( pRow[nI], rExport ) ) 2464 { 2465 bHasGraphic = true; 2466 break; 2467 } 2468 } 2469 return bHasGraphic; 2470 } 2471 #endif 2472 //--------------------------------------------------------------------------- 2473 // Tabellen 2474 //--------------------------------------------------------------------------- 2475 2476 void WW8AttributeOutput::EmptyParagraph() 2477 { 2478 m_rWW8Export.WriteStringAsPara( aEmptyStr ); 2479 } 2480 2481 bool MSWordExportBase::NoPageBreakSection( const SfxItemSet* pSet ) 2482 { 2483 bool bRet = false; 2484 const SfxPoolItem* pI; 2485 if( pSet) 2486 { 2487 bool bNoPageBreak = false; 2488 if ( SFX_ITEM_ON != pSet->GetItemState(RES_PAGEDESC, true, &pI) 2489 || 0 == ((SwFmtPageDesc*)pI)->GetPageDesc() ) 2490 { 2491 bNoPageBreak = true; 2492 } 2493 2494 if (bNoPageBreak) 2495 { 2496 if (SFX_ITEM_ON != pSet->GetItemState(RES_BREAK, true, &pI)) 2497 bNoPageBreak = true; 2498 else 2499 { 2500 SvxBreak eBreak = ((const SvxFmtBreakItem*)pI)->GetBreak(); 2501 switch (eBreak) 2502 { 2503 case SVX_BREAK_PAGE_BEFORE: 2504 case SVX_BREAK_PAGE_AFTER: 2505 bNoPageBreak = false; 2506 break; 2507 default: 2508 break; 2509 } 2510 } 2511 } 2512 bRet = bNoPageBreak; 2513 } 2514 return bRet; 2515 } 2516 2517 /* */ 2518 2519 void MSWordExportBase::OutputSectionNode( const SwSectionNode& rSectionNode ) 2520 { 2521 const SwSection& rSection = rSectionNode.GetSection(); 2522 2523 SwNodeIndex aIdx( rSectionNode, 1 ); 2524 const SwNode& rNd = aIdx.GetNode(); 2525 if ( !rNd.IsSectionNode() && !IsInTable() 2526 && rSection.GetType() != TOX_CONTENT_SECTION && rSection.GetType() != TOX_HEADER_SECTION) //No sections in table 2527 { 2528 // Bug 74245 - if the first Node inside the section has an own 2529 // PageDesc or PageBreak attribut, then dont write 2530 // here the section break 2531 sal_uLong nRstLnNum = 0; 2532 const SfxItemSet* pSet; 2533 if ( rNd.IsTableNode() ) 2534 pSet = &rNd.GetTableNode()->GetTable().GetFrmFmt()->GetAttrSet(); 2535 else if ( rNd.IsCntntNode() ) 2536 { 2537 pSet = &rNd.GetCntntNode()->GetSwAttrSet(); 2538 nRstLnNum = ((SwFmtLineNumber&)pSet->Get( 2539 RES_LINENUMBER )).GetStartValue(); 2540 } 2541 else 2542 pSet = 0; 2543 2544 if ( pSet && NoPageBreakSection( pSet ) ) 2545 pSet = 0; 2546 2547 if ( !pSet ) 2548 { 2549 // new Section with no own PageDesc/-Break 2550 // -> write follow section break; 2551 const SwSectionFmt& rFmt = *rSection.GetFmt(); 2552 ReplaceCr( msword::PageBreak ); // Indikator fuer Page/Section-Break 2553 2554 //Get the page in use at the top of this section 2555 SwNodeIndex aIdxTmp(rSectionNode, 1); 2556 const SwPageDesc *pCurrent = 2557 SwPageDesc::GetPageDescOfNode(aIdxTmp.GetNode()); 2558 if (!pCurrent) 2559 pCurrent = pAktPageDesc; 2560 2561 AppendSection( pCurrent, &rFmt, nRstLnNum ); 2562 } 2563 } 2564 if ( TOX_CONTENT_SECTION == rSection.GetType() ) 2565 bStartTOX = true; 2566 } 2567 2568 2569 void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum ) 2570 { 2571 pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFmt, nLnNum); 2572 } 2573 2574 /* */ 2575 2576 //--------------------------------------------------------------------------- 2577 // Flys 2578 //--------------------------------------------------------------------------- 2579 2580 void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode& rNd ) 2581 { 2582 ASSERT(!bWrtWW8, "I shouldn't be needed for Word >=8"); 2583 if ( bWrtWW8 ) 2584 return; 2585 2586 if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints()) 2587 { 2588 for( sal_uInt16 n=0; n < pTxtAttrs->Count(); ++n ) 2589 { 2590 const SwTxtAttr* pAttr = (*pTxtAttrs)[ n ]; 2591 if( RES_TXTATR_FLYCNT == pAttr->Which() ) 2592 { 2593 // zeichengebundenes Attribut 2594 const SwFmtFlyCnt& rFlyCntnt = pAttr->GetFlyCnt(); 2595 const SwFlyFrmFmt& rFlyFrmFmt = *(SwFlyFrmFmt*)rFlyCntnt.GetFrmFmt(); 2596 const SwNodeIndex* pNodeIndex = rFlyFrmFmt.GetCntnt().GetCntntIdx(); 2597 2598 if( pNodeIndex ) 2599 { 2600 sal_uLong nStt = pNodeIndex->GetIndex()+1, 2601 nEnd = pNodeIndex->GetNode().EndOfSectionIndex(); 2602 2603 if( (nStt < nEnd) && !pDoc->GetNodes()[ nStt ]->IsNoTxtNode() ) 2604 { 2605 Point aOffset; 2606 // Rechtecke des Flys und des Absatzes besorgen 2607 SwRect aParentRect(rNd.FindLayoutRect(false, &aOffset)), 2608 aFlyRect(rFlyFrmFmt.FindLayoutRect(false, &aOffset ) ); 2609 2610 aOffset = aFlyRect.Pos() - aParentRect.Pos(); 2611 2612 // PaM umsetzen: auf Inhalt des Fly-Frameformats 2613 SaveData( nStt, nEnd ); 2614 2615 // wird in OutputFormat() ausgewertet 2616 pFlyOffset = &aOffset; 2617 eNewAnchorType = rFlyFrmFmt.GetAnchor().GetAnchorId(); 2618 sw::Frame aFrm(rFlyFrmFmt, SwPosition(rNd)); 2619 mpParentFrame = &aFrm; 2620 // Ok, rausschreiben: 2621 WriteText(); 2622 2623 RestoreData(); 2624 } 2625 } 2626 } 2627 } 2628 } 2629 } 2630 2631 void WW8AttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft ) 2632 { 2633 const SwFrmFmt &rFrmFmt = rFmt.GetFrmFmt(); 2634 const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor(); 2635 2636 bool bUseEscher = m_rWW8Export.bWrtWW8; 2637 2638 if ( m_rWW8Export.bWrtWW8 && rFmt.IsInline() ) 2639 { 2640 sw::Frame::WriterSource eType = rFmt.GetWriterType(); 2641 if ((eType == sw::Frame::eGraphic) || (eType == sw::Frame::eOle)) 2642 bUseEscher = false; 2643 else 2644 bUseEscher = true; 2645 2646 /* 2647 #110185# 2648 A special case for converting some inline form controls to form fields 2649 when in winword 8+ mode 2650 */ 2651 if ((bUseEscher == true) && (eType == sw::Frame::eFormControl)) 2652 { 2653 if ( m_rWW8Export.MiserableFormFieldExportHack( rFrmFmt ) ) 2654 return ; 2655 } 2656 } 2657 2658 if (bUseEscher) 2659 { 2660 ASSERT( m_rWW8Export.bWrtWW8, "this has gone horribly wrong" ); 2661 // write as escher 2662 m_rWW8Export.AppendFlyInFlys(rFmt, rNdTopLeft); 2663 } 2664 else 2665 { 2666 bool bDone = false; 2667 2668 // Hole vom Node und vom letzten Node die Position in der Section 2669 const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx(); 2670 2671 sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0; 2672 sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0; 2673 2674 if( nStt >= nEnd ) // kein Bereich, also kein gueltiger Node 2675 return; 2676 2677 if ( !m_rWW8Export.IsInTable() && rFmt.IsInline() ) 2678 { 2679 //Test to see if this textbox contains only a single graphic/ole 2680 SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode(); 2681 if ( pParTxtNode && !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode() ) 2682 bDone = true; 2683 } 2684 if( !bDone ) 2685 { 2686 // ein NICHT zeichengebundener Rahmen liegt vor 2687 2688 // --> OD 2007-04-19 #i43447# - removed 2689 // const SwFmtFrmSize& rS = rFrmFmt.GetFrmSize(); 2690 // nFlyWidth = rS.GetWidth(); // Fuer Anpassung Graphic-Groesse 2691 // nFlyHeight = rS.GetHeight(); 2692 // <-- 2693 2694 m_rWW8Export.SaveData( nStt, nEnd ); 2695 2696 Point aOffset; 2697 if ( m_rWW8Export.mpParentFrame ) 2698 { 2699 /* 2700 #90804# 2701 Munge flys in fly into absolutely positioned elements for 2702 word 6 2703 */ 2704 const SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode(); 2705 const SwRect aPageRect = pParTxtNode->FindPageFrmRect( sal_False, 0, sal_False ); 2706 2707 aOffset = rFrmFmt.FindLayoutRect().Pos(); 2708 aOffset -= aPageRect.Pos(); 2709 2710 m_rWW8Export.pFlyOffset = &aOffset; 2711 m_rWW8Export.eNewAnchorType = FLY_AT_PAGE; 2712 } 2713 2714 m_rWW8Export.mpParentFrame = &rFmt; 2715 if ( 2716 m_rWW8Export.IsInTable() && 2717 (FLY_AT_PAGE != rAnch.GetAnchorId()) && 2718 !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode() 2719 ) 2720 { 2721 // Beachten: Flag bOutTable wieder setzen, 2722 // denn wir geben ja ganz normalen Content der 2723 // Tabelenzelle aus und keinen Rahmen 2724 // (Flag wurde oben in aSaveData() geloescht) 2725 m_rWW8Export.bOutTable = true; 2726 const String& rName = rFrmFmt.GetName(); 2727 m_rWW8Export.StartCommentOutput(rName); 2728 m_rWW8Export.WriteText(); 2729 m_rWW8Export.EndCommentOutput(rName); 2730 } 2731 else 2732 m_rWW8Export.WriteText(); 2733 2734 m_rWW8Export.RestoreData(); 2735 } 2736 } 2737 } 2738 2739 void AttributeOutputBase::OutputFlyFrame( const sw::Frame& rFmt ) 2740 { 2741 if ( !rFmt.GetCntntNode() ) 2742 return; 2743 2744 const SwCntntNode &rNode = *rFmt.GetCntntNode(); 2745 Point aNdPos, aPgPos; 2746 Point* pLayPos; 2747 bool bValidNdPos = false, bValidPgPos = false; 2748 2749 if (FLY_AT_PAGE == rFmt.GetFrmFmt().GetAnchor().GetAnchorId()) 2750 { 2751 // get the Layout Node-Position. 2752 if ( !bValidPgPos ) 2753 { 2754 aPgPos = rNode.FindPageFrmRect(false, &aPgPos).Pos(); 2755 bValidPgPos = true; 2756 } 2757 pLayPos = &aPgPos; 2758 } 2759 else 2760 { 2761 // get the Layout Node-Position. 2762 if ( !bValidNdPos ) 2763 { 2764 aNdPos = rNode.FindLayoutRect(false, &aNdPos).Pos(); 2765 bValidNdPos = true; 2766 } 2767 pLayPos = &aNdPos; 2768 } 2769 2770 OutputFlyFrame_Impl( rFmt, *pLayPos ); 2771 } 2772 2773 // write data of any redline 2774 void WW8AttributeOutput::Redline( const SwRedlineData* pRedline ) 2775 { 2776 if ( !pRedline ) 2777 return; 2778 2779 if ( pRedline->Next() ) 2780 Redline( pRedline->Next() ); 2781 2782 static sal_uInt16 __READONLY_DATA aSprmIds[ 2 * 2 * 3 ] = 2783 { 2784 // Ids for insert 2785 NS_sprm::LN_CFRMark, NS_sprm::LN_CIbstRMark, NS_sprm::LN_CDttmRMark, // for WW8 2786 0x0042, 0x0045, 0x0046, // for WW6 2787 // Ids for delete 2788 NS_sprm::LN_CFRMarkDel, NS_sprm::LN_CIbstRMarkDel, NS_sprm::LN_CDttmRMarkDel, // for WW8 2789 0x0041, 0x0045, 0x0046 // for WW6 2790 }; 2791 2792 const sal_uInt16* pSprmIds = 0; 2793 switch( pRedline->GetType() ) 2794 { 2795 case nsRedlineType_t::REDLINE_INSERT: 2796 pSprmIds = aSprmIds; 2797 break; 2798 2799 case nsRedlineType_t::REDLINE_DELETE: 2800 pSprmIds = aSprmIds + (2 * 3); 2801 break; 2802 2803 case nsRedlineType_t::REDLINE_FORMAT: 2804 if( m_rWW8Export.bWrtWW8 ) 2805 { 2806 m_rWW8Export.InsUInt16( NS_sprm::LN_CPropRMark ); 2807 m_rWW8Export.pO->Insert( 7, m_rWW8Export.pO->Count() ); // len 2808 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() ); 2809 m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) ); 2810 m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() )); 2811 } 2812 break; 2813 default: 2814 ASSERT(!this, "Unhandled redline type for export"); 2815 break; 2816 } 2817 2818 if ( pSprmIds ) 2819 { 2820 if ( !m_rWW8Export.bWrtWW8 ) 2821 pSprmIds += 3; 2822 2823 if ( m_rWW8Export.bWrtWW8 ) 2824 m_rWW8Export.InsUInt16( pSprmIds[0] ); 2825 else 2826 m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[0]), m_rWW8Export.pO->Count() ); 2827 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() ); 2828 2829 if ( m_rWW8Export.bWrtWW8 ) 2830 m_rWW8Export.InsUInt16( pSprmIds[1] ); 2831 else 2832 m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[1]), m_rWW8Export.pO->Count() ); 2833 m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) ); 2834 2835 if ( m_rWW8Export.bWrtWW8 ) 2836 m_rWW8Export.InsUInt16( pSprmIds[2] ); 2837 else 2838 m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[2]), m_rWW8Export.pO->Count() ); 2839 m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() )); 2840 } 2841 } 2842 2843 /* */ 2844 2845 void MSWordExportBase::OutputContentNode( const SwCntntNode& rNode ) 2846 { 2847 switch ( rNode.GetNodeType() ) 2848 { 2849 case ND_TEXTNODE: 2850 { 2851 const SwTxtNode& rTextNode = *rNode.GetTxtNode(); 2852 if( !mbOutOutlineOnly || rTextNode.IsOutline() ) 2853 OutputTextNode( rTextNode ); 2854 } 2855 break; 2856 case ND_GRFNODE: 2857 OutputGrfNode( *rNode.GetGrfNode() ); 2858 break; 2859 case ND_OLENODE: 2860 OutputOLENode( *rNode.GetOLENode() ); 2861 break; 2862 default: 2863 #if OSL_DEBUG_LEVEL > 0 2864 OSL_TRACE("Unhandled node, type == %d\n", rNode.GetNodeType() ); 2865 #endif 2866 break; 2867 } 2868 } 2869 2870 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 2871