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 27 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ 28 29 #include <algorithm> 30 #include <functional> 31 32 #include <boost/scoped_array.hpp> 33 34 #include <com/sun/star/i18n/ScriptType.hdl> 35 #include <rtl/tencinfo.h> 36 #include <hintids.hxx> 37 #include <editeng/boxitem.hxx> 38 #include <editeng/fontitem.hxx> 39 #include <svx/svdobj.hxx> 40 #include <svx/svdotext.hxx> 41 #include <svx/svdotext.hxx> 42 #include <svx/fmglob.hxx> 43 #include <editeng/frmdiritem.hxx> 44 #include <editeng/lrspitem.hxx> 45 #include <editeng/ulspitem.hxx> 46 #include <doc.hxx> 47 #include <wrtww8.hxx> 48 #include <docary.hxx> 49 #include <poolfmt.hxx> 50 #include <fmtpdsc.hxx> 51 #include <pagedesc.hxx> 52 #include <ndtxt.hxx> 53 #include <ftninfo.hxx> 54 #include <fmthdft.hxx> 55 #include <section.hxx> 56 #include <fmtcntnt.hxx> 57 #include <fmtftn.hxx> 58 #include <ndindex.hxx> 59 #include <txtftn.hxx> 60 #include <charfmt.hxx> 61 #include <docufld.hxx> 62 #include <dcontact.hxx> 63 #include <fmtcnct.hxx> 64 #include <ftnidx.hxx> 65 #include <fmtclds.hxx> 66 #include <lineinfo.hxx> 67 #include <fmtline.hxx> 68 #include <swtable.hxx> 69 #include <msfilter.hxx> 70 #include <swmodule.hxx> 71 72 #include <writerfilter/doctok/sprmids.hxx> 73 74 #include "writerhelper.hxx" 75 #include "writerwordglue.hxx" 76 #include "../inc/wwstyles.hxx" 77 #include "ww8par.hxx" 78 #include "ww8attributeoutput.hxx" 79 #include "docxattributeoutput.hxx" 80 #include "rtfattributeoutput.hxx" 81 82 using namespace sw::util; 83 using namespace nsHdFtFlags; 84 85 /// For the output of sections. 86 struct WW8_PdAttrDesc 87 { 88 ::boost::scoped_array<sal_uInt8> m_pData; 89 sal_uInt16 m_nLen; 90 WW8_FC m_nSepxFcPos; 91 WW8_PdAttrDesc() : m_nLen(0), m_nSepxFcPos(0xffffffff) /*default: none*/ 92 { } 93 }; 94 95 struct WW8_SED 96 { 97 SVBT16 aBits1; // orientation change + internal, Default: 6 98 SVBT32 fcSepx; // FC file offset to beginning of SEPX for section. 99 // 0xFFFFFFFF for no Sprms 100 SVBT16 fnMpr; // used internally by Windows Word, Default: 0 101 SVBT32 fcMpr; // FC, points to offset in FC space for MacWord 102 // Default: 0xffffffff ( nothing ) 103 // cbSED is 12 (decimal)), C (hex). 104 }; 105 106 SV_IMPL_VARARR( WW8_WrSepInfoPtrs, WW8_SepInfo ) 107 108 // class WW8_WrPlc0 ist erstmal nur fuer Header / Footer-Positionen, d.h. es 109 // gibt keine inhaltstragende Struktur. 110 class WW8_WrPlc0 111 { 112 private: 113 SvULongs aPos; // PTRARR von CPs / FCs 114 sal_uLong nOfs; 115 116 //No copying 117 WW8_WrPlc0(const WW8_WrPlc0&); 118 WW8_WrPlc0 &operator=(const WW8_WrPlc0&); 119 public: 120 WW8_WrPlc0( sal_uLong nOffset ); 121 sal_uInt16 Count() const { return aPos.Count(); } 122 void Append( sal_uLong nStartCpOrFc ); 123 void Write( SvStream& rStrm ); 124 }; 125 126 //------------------------------------------------------------ 127 // Styles 128 //------------------------------------------------------------ 129 130 #define WW8_RESERVED_SLOTS 15 131 132 // GetId( SwCharFmt ) zur Benutzung im Text -> nil verboten, 133 // "Default Char Style" stattdessen 134 sal_uInt16 MSWordExportBase::GetId( const SwCharFmt& rFmt ) const 135 { 136 sal_uInt16 nRet = pStyles->GetSlot( rFmt ); 137 return ( nRet != 0x0fff ) ? nRet : 10; // Default Char Style 138 } 139 140 // GetId( SwTxtFmtColl ) zur Benutzung an TextNodes -> nil verboten, 141 // "Standard" stattdessen 142 sal_uInt16 MSWordExportBase::GetId( const SwTxtFmtColl& rColl ) const 143 { 144 sal_uInt16 nRet = pStyles->GetSlot( rColl ); 145 return ( nRet != 0xfff ) ? nRet : 0; // Default TxtFmtColl 146 } 147 148 149 150 //typedef pFmtT 151 MSWordStyles::MSWordStyles( MSWordExportBase& rExport ) 152 : m_rExport( rExport ) 153 { 154 // if exist any Foot-/End-Notes then get from the EndNoteInfo struct 155 // the CharFormats. They will create it! 156 if ( m_rExport.pDoc->GetFtnIdxs().Count() ) 157 { 158 m_rExport.pDoc->GetEndNoteInfo().GetAnchorCharFmt( *m_rExport.pDoc ); 159 m_rExport.pDoc->GetEndNoteInfo().GetCharFmt( *m_rExport.pDoc ); 160 m_rExport.pDoc->GetFtnInfo().GetAnchorCharFmt( *m_rExport.pDoc ); 161 m_rExport.pDoc->GetFtnInfo().GetCharFmt( *m_rExport.pDoc ); 162 } 163 sal_uInt16 nAlloc = WW8_RESERVED_SLOTS + m_rExport.pDoc->GetCharFmts()->Count() - 1 + 164 m_rExport.pDoc->GetTxtFmtColls()->Count() - 1; 165 166 // etwas grosszuegig ( bis zu 15 frei ) 167 pFmtA = new SwFmt*[ nAlloc ]; 168 memset( pFmtA, 0, nAlloc * sizeof( SwFmt* ) ); 169 170 BuildStylesTable(); 171 } 172 173 MSWordStyles::~MSWordStyles() 174 { 175 delete[] pFmtA; 176 } 177 178 // Sty_SetWWSlot() fuer Abhaengigkeiten der Styles -> nil ist erlaubt 179 sal_uInt16 MSWordStyles::GetSlot( const SwFmt& rFmt ) const 180 { 181 sal_uInt16 n; 182 for ( n = 0; n < nUsedSlots; n++ ) 183 if ( pFmtA[n] == &rFmt ) 184 return n; 185 return 0xfff; // 0xfff: WW: nil 186 } 187 188 sal_uInt16 MSWordStyles::BuildGetSlot( const SwFmt& rFmt ) 189 { 190 sal_uInt16 nRet; 191 switch ( nRet = rFmt.GetPoolFmtId() ) 192 { 193 case RES_POOLCOLL_STANDARD: 194 nRet = 0; 195 break; 196 197 case RES_POOLCOLL_HEADLINE1: 198 case RES_POOLCOLL_HEADLINE2: 199 case RES_POOLCOLL_HEADLINE3: 200 case RES_POOLCOLL_HEADLINE4: 201 case RES_POOLCOLL_HEADLINE5: 202 case RES_POOLCOLL_HEADLINE6: 203 case RES_POOLCOLL_HEADLINE7: 204 case RES_POOLCOLL_HEADLINE8: 205 case RES_POOLCOLL_HEADLINE9: 206 nRet -= RES_POOLCOLL_HEADLINE1-1; 207 break; 208 209 //case RES_POOLCHR_FOOTNOTE_ANCHOR: nRet = 210 //case RES_POOLCHR_ENDNOTE_ANCHOR: 211 default: 212 nRet = nUsedSlots++; 213 break; 214 } 215 return nRet; 216 } 217 218 sal_uInt16 MSWordStyles::GetWWId( const SwFmt& rFmt ) const 219 { 220 sal_uInt16 nRet = ww::stiUser; // User-Style als default 221 sal_uInt16 nPoolId = rFmt.GetPoolFmtId(); 222 if( nPoolId == RES_POOLCOLL_STANDARD ) 223 nRet = 0; 224 else if( nPoolId >= RES_POOLCOLL_HEADLINE1 && 225 nPoolId <= RES_POOLCOLL_HEADLINE9 ) 226 nRet = static_cast< sal_uInt16 >(nPoolId + 1 - RES_POOLCOLL_HEADLINE1); 227 else if( nPoolId >= RES_POOLCOLL_TOX_IDX1 && 228 nPoolId <= RES_POOLCOLL_TOX_IDX3 ) 229 nRet = static_cast< sal_uInt16 >(nPoolId + 10 - RES_POOLCOLL_TOX_IDX1); 230 else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT1 && 231 nPoolId <= RES_POOLCOLL_TOX_CNTNT5 ) 232 nRet = static_cast< sal_uInt16 >(nPoolId + 19 - RES_POOLCOLL_TOX_CNTNT1); 233 else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT6 && 234 nPoolId <= RES_POOLCOLL_TOX_CNTNT9 ) 235 nRet = static_cast< sal_uInt16 >(nPoolId + 24 - RES_POOLCOLL_TOX_CNTNT6); 236 else 237 switch( nPoolId ) 238 { 239 case RES_POOLCOLL_FOOTNOTE: nRet = 29; break; 240 case RES_POOLCOLL_HEADER: nRet = 31; break; 241 case RES_POOLCOLL_FOOTER: nRet = 32; break; 242 case RES_POOLCOLL_TOX_IDXH: nRet = 33; break; 243 case RES_POOLCOLL_JAKETADRESS: nRet = 36; break; 244 case RES_POOLCOLL_SENDADRESS: nRet = 37; break; 245 case RES_POOLCOLL_ENDNOTE: nRet = 43; break; 246 case RES_POOLCOLL_LISTS_BEGIN: nRet = 47; break; 247 case RES_POOLCOLL_DOC_TITEL: nRet = 62; break; 248 case RES_POOLCOLL_SIGNATURE: nRet = 64; break; 249 case RES_POOLCOLL_TEXT: nRet = 66; break; 250 case RES_POOLCOLL_TEXT_MOVE: nRet = 67; break; 251 case RES_POOLCOLL_DOC_SUBTITEL: nRet = 74; break; 252 case RES_POOLCOLL_TEXT_IDENT: nRet = 77; break; 253 254 case RES_POOLCHR_FOOTNOTE_ANCHOR: nRet = 38; break; 255 case RES_POOLCHR_ENDNOTE_ANCHOR: nRet = 42; break; 256 case RES_POOLCHR_INET_NORMAL: nRet = 85; break; 257 case RES_POOLCHR_INET_VISIT: nRet = 86; break; 258 case RES_POOLCHR_HTML_STRONG: nRet = 87; break; 259 case RES_POOLCHR_HTML_EMPHASIS: nRet = 88; break; 260 case RES_POOLCHR_LINENUM: nRet = 40; break; 261 case RES_POOLCHR_PAGENO: nRet = 41; break; 262 } 263 return nRet; 264 } 265 266 void MSWordStyles::BuildStylesTable() 267 { 268 nUsedSlots = WW8_RESERVED_SLOTS; // soviele sind reserviert fuer 269 // Standard und HeadingX u.a. 270 SwFmt* pFmt; 271 sal_uInt16 n; 272 const SvPtrarr& rArr = *m_rExport.pDoc->GetCharFmts(); // erst CharFmt 273 // das Default-ZeichenStyle ( 0 ) wird nicht mit ausgegeben ! 274 for( n = 1; n < rArr.Count(); n++ ) 275 { 276 pFmt = (SwFmt*)rArr[n]; 277 pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt; 278 } 279 280 const SvPtrarr& rArr2 = *m_rExport.pDoc->GetTxtFmtColls(); // dann TxtFmtColls 281 // das Default-TextStyle ( 0 ) wird nicht mit ausgegeben ! 282 for( n = 1; n < rArr2.Count(); n++ ) 283 { 284 pFmt = (SwFmt*)rArr2[n]; 285 pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt; 286 } 287 } 288 289 /// For WW8 only - extend pO so that the size of pTableStrm is even. 290 static void impl_SkipOdd( WW8Bytes* pO, sal_Size nTableStrmTell ) 291 { 292 if ( ( nTableStrmTell + pO->Count() ) & 1 ) // Start auf gerader 293 pO->Insert( (sal_uInt8)0, pO->Count() ); // Adresse 294 } 295 296 void WW8AttributeOutput::EndStyle() 297 { 298 impl_SkipOdd( m_rWW8Export.pO, m_rWW8Export.pTableStrm->Tell() ); 299 300 short nLen = m_rWW8Export.pO->Count() - 2; // Laenge des Styles 301 sal_uInt8* p = (sal_uInt8*)m_rWW8Export.pO->GetData() + nPOPosStdLen1; 302 ShortToSVBT16( nLen, p ); // nachtragen 303 p = (sal_uInt8*)m_rWW8Export.pO->GetData() + nPOPosStdLen2; 304 ShortToSVBT16( nLen, p ); // dito 305 306 m_rWW8Export.pTableStrm->Write( m_rWW8Export.pO->GetData(), m_rWW8Export.pO->Count() ); // ins File damit 307 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren fuer naechsten 308 } 309 310 void WW8AttributeOutput::StartStyle( const String& rName, bool bPapFmt, sal_uInt16 nWwBase, 311 sal_uInt16 nWwNext, sal_uInt16 nWwId, sal_uInt16 /*nId*/ ) 312 { 313 sal_uInt8 aWW8_STD[ sizeof( WW8_STD ) ]; 314 sal_uInt8* pData = aWW8_STD; 315 memset( &aWW8_STD, 0, sizeof( WW8_STD ) ); 316 317 sal_uInt16 nBit16 = 0x1000; // fInvalHeight 318 nBit16 |= (ww::stiNil & nWwId); 319 Set_UInt16( pData, nBit16 ); 320 321 nBit16 = nWwBase << 4; // istdBase 322 nBit16 |= bPapFmt ? 1 : 2; // sgc 323 Set_UInt16( pData, nBit16 ); 324 325 nBit16 = nWwNext << 4; // istdNext 326 nBit16 |= bPapFmt ? 2 : 1; // cupx 327 Set_UInt16( pData, nBit16 ); 328 329 pData += sizeof( sal_uInt16 ); // bchUpe 330 331 if( m_rWW8Export.bWrtWW8 ) 332 { 333 //-------- jetzt neu: 334 // ab Ver8 gibts zwei Felder mehr: 335 //sal_uInt16 fAutoRedef : 1; /* auto redefine style when appropriate */ 336 //sal_uInt16 fHidden : 1; /* hidden from UI? */ 337 //sal_uInt16 : 14; /* unused bits */ 338 pData += sizeof( sal_uInt16 ); 339 } 340 341 342 sal_uInt16 nLen = static_cast< sal_uInt16 >( ( pData - aWW8_STD ) + 1 + 343 ((m_rWW8Export.bWrtWW8 ? 2 : 1 ) * (rName.Len() + 1)) ); // vorlaeufig 344 345 WW8Bytes* pO = m_rWW8Export.pO; 346 nPOPosStdLen1 = pO->Count(); // Adr1 zum nachtragen der Laenge 347 348 SwWW8Writer::InsUInt16( *pO, nLen ); 349 pO->Insert( aWW8_STD, static_cast< sal_uInt16 >( pData - aWW8_STD ), pO->Count() ); 350 351 nPOPosStdLen2 = nPOPosStdLen1 + 8; // Adr2 zum nachtragen von "end of upx" 352 353 // Namen schreiben 354 if( m_rWW8Export.bWrtWW8 ) 355 { 356 SwWW8Writer::InsUInt16( *pO, rName.Len() ); // Laenge 357 SwWW8Writer::InsAsString16( *pO, rName ); 358 } 359 else 360 { 361 pO->Insert( (sal_uInt8)rName.Len(), pO->Count() ); // Laenge 362 SwWW8Writer::InsAsString8( *pO, rName, RTL_TEXTENCODING_MS_1252 ); 363 } 364 pO->Insert( (sal_uInt8)0, pO->Count() ); // Trotz P-String 0 am Ende! 365 } 366 367 void MSWordStyles::SetStyleDefaults( const SwFmt& rFmt, bool bPap ) 368 { 369 const SwModify* pOldMod = m_rExport.pOutFmtNode; 370 m_rExport.pOutFmtNode = &rFmt; 371 bool aFlags[ static_cast< sal_uInt16 >(RES_FRMATR_END) - RES_CHRATR_BEGIN ]; 372 sal_uInt16 nStt, nEnd, n; 373 if( bPap ) 374 nStt = RES_PARATR_BEGIN, nEnd = RES_FRMATR_END; 375 else 376 nStt = RES_CHRATR_BEGIN, nEnd = RES_TXTATR_END; 377 378 // dynamic defaults 379 const SfxItemPool& rPool = *rFmt.GetAttrSet().GetPool(); 380 for( n = nStt; n < nEnd; ++n ) 381 aFlags[ n - RES_CHRATR_BEGIN ] = 0 != rPool.GetPoolDefaultItem( n ); 382 383 // static defaults, that differs between WinWord and SO 384 if( bPap ) 385 { 386 aFlags[ static_cast< sal_uInt16 >(RES_PARATR_WIDOWS) - RES_CHRATR_BEGIN ] = 1; 387 aFlags[ static_cast< sal_uInt16 >(RES_PARATR_HYPHENZONE) - RES_CHRATR_BEGIN ] = 1; 388 } 389 else 390 { 391 aFlags[ RES_CHRATR_FONTSIZE - RES_CHRATR_BEGIN ] = 1; 392 aFlags[ RES_CHRATR_LANGUAGE - RES_CHRATR_BEGIN ] = 1; 393 } 394 395 const SfxItemSet* pOldI = m_rExport.GetCurItemSet(); 396 m_rExport.SetCurItemSet( &rFmt.GetAttrSet() ); 397 398 const bool* pFlags = aFlags + ( nStt - RES_CHRATR_BEGIN ); 399 for ( n = nStt; n < nEnd; ++n, ++pFlags ) 400 { 401 if ( *pFlags && SFX_ITEM_SET != rFmt.GetItemState(n, false)) 402 { 403 //If we are a character property then see if it is one of the 404 //western/asian ones that must be collapsed together for export to 405 //word. If so default to the western varient. 406 if ( bPap || m_rExport.CollapseScriptsforWordOk( 407 i18n::ScriptType::LATIN, n) ) 408 { 409 m_rExport.AttrOutput().OutputItem( rFmt.GetFmtAttr( n, true ) ); 410 } 411 } 412 } 413 414 m_rExport.SetCurItemSet( pOldI ); 415 m_rExport.pOutFmtNode = pOldMod; 416 } 417 418 void WW8AttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 nStyle ) 419 { 420 WW8Bytes* pO = m_rWW8Export.pO; 421 422 impl_SkipOdd( pO, m_rWW8Export.pTableStrm->Tell() ); 423 424 sal_uInt16 nLen = ( bParProp ) ? 2 : 0; // Default-Laenge 425 m_nStyleLenPos = pO->Count(); // Laenge zum Nachtragen 426 // Keinen Pointer merken, da sich bei 427 // _grow der Pointer aendert ! 428 429 SwWW8Writer::InsUInt16( *pO, nLen ); // Style-Len 430 431 m_nStyleStartSize = pO->Count(); 432 433 if ( bParProp ) 434 SwWW8Writer::InsUInt16( *pO, nStyle ); // Style-Nummer 435 } 436 437 void MSWordStyles::WriteProperties( const SwFmt* pFmt, bool bParProp, sal_uInt16 nPos, 438 bool bInsDefCharSiz ) 439 { 440 m_rExport.AttrOutput().StartStyleProperties( bParProp, nPos ); 441 442 ASSERT( m_rExport.pCurrentStyle == NULL, "Current style not NULL" ); // set current style before calling out 443 m_rExport.pCurrentStyle = pFmt; 444 445 m_rExport.OutputFormat( *pFmt, bParProp, !bParProp ); 446 447 ASSERT( m_rExport.pCurrentStyle == pFmt, "current style was changed" ); 448 // reset current style... 449 m_rExport.pCurrentStyle = NULL; 450 451 if ( bInsDefCharSiz ) // nicht abgeleitet v. anderem Style 452 SetStyleDefaults( *pFmt, bParProp ); 453 454 m_rExport.AttrOutput().EndStyleProperties( bParProp ); 455 } 456 457 void WW8AttributeOutput::EndStyleProperties( bool /*bParProp*/ ) 458 { 459 WW8Bytes* pO = m_rWW8Export.pO; 460 461 sal_uInt16 nLen = pO->Count() - m_nStyleStartSize; 462 sal_uInt8* pUpxLen = (sal_uInt8*)pO->GetData() + m_nStyleLenPos; // Laenge zum Nachtragen 463 ShortToSVBT16( nLen, pUpxLen ); // Default-Laenge eintragen 464 } 465 466 void MSWordStyles::GetStyleData( SwFmt* pFmt, bool& bFmtColl, sal_uInt16& nBase, sal_uInt16& nNext ) 467 { 468 bFmtColl = pFmt->Which() == RES_TXTFMTCOLL || pFmt->Which() == RES_CONDTXTFMTCOLL; 469 470 // Default: none 471 nBase = 0xfff; 472 473 // Derived from? 474 if ( !pFmt->IsDefault() ) 475 nBase = GetSlot( *pFmt->DerivedFrom() ); 476 477 SwFmt* pNext; 478 if ( bFmtColl ) 479 pNext = &((SwTxtFmtColl*)pFmt)->GetNextTxtFmtColl(); 480 else 481 pNext = pFmt; // CharFmt: next CharFmt == self 482 483 nNext = GetSlot( *pNext ); 484 } 485 486 void WW8AttributeOutput::DefaultStyle( sal_uInt16 nStyle ) 487 { 488 if ( nStyle == 10 ) // Default Char-Style ( nur WW ) 489 { 490 if ( m_rWW8Export.bWrtWW8 ) 491 { 492 sal_uInt16 n = 0; 493 m_rWW8Export.pTableStrm->Write( &n , 2 ); // empty Style 494 } 495 else 496 { 497 static sal_uInt8 __READONLY_DATA aDefCharSty[] = { 498 0x26, 0x00, 499 0x41, 0x40, 0xF2, 0xFF, 0xA1, 0x00, 0x26, 0x00, 500 0x19, 0x41, 0x62, 0x73, 0x61, 0x74, 0x7A, 0x2D, 501 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 502 0x73, 0x63, 0x68, 0x72, 0x69, 0x66, 0x74, 0x61, 503 0x72, 0x74, 0x00, 0x00, 0x00, 0x00 }; 504 m_rWW8Export.pTableStrm->Write( &aDefCharSty, sizeof( aDefCharSty ) ); 505 } 506 } 507 else 508 { 509 sal_uInt16 n = 0; 510 m_rWW8Export.pTableStrm->Write( &n , 2 ); // empty Style 511 } 512 } 513 514 // OutputStyle geht fuer TxtFmtColls und CharFmts 515 void MSWordStyles::OutputStyle( SwFmt* pFmt, sal_uInt16 nPos ) 516 { 517 if ( !pFmt ) 518 m_rExport.AttrOutput().DefaultStyle( nPos ); 519 else 520 { 521 bool bFmtColl; 522 sal_uInt16 nBase, nWwNext; 523 524 GetStyleData( pFmt, bFmtColl, nBase, nWwNext ); 525 526 m_rExport.AttrOutput().StartStyle( pFmt->GetName(), bFmtColl, 527 nBase, nWwNext, GetWWId( *pFmt ), nPos ); 528 529 if ( bFmtColl ) 530 WriteProperties( pFmt, true, nPos, nBase==0xfff ); // UPX.papx 531 532 WriteProperties( pFmt, false, nPos, bFmtColl && nBase==0xfff ); // UPX.chpx 533 534 m_rExport.AttrOutput().EndStyle(); 535 } 536 } 537 538 void WW8AttributeOutput::StartStyles() 539 { 540 WW8Fib& rFib = *m_rWW8Export.pFib; 541 542 sal_uLong nCurPos = m_rWW8Export.pTableStrm->Tell(); 543 if ( nCurPos & 1 ) // Start auf gerader 544 { 545 *m_rWW8Export.pTableStrm << (char)0; // Adresse 546 ++nCurPos; 547 } 548 rFib.fcStshfOrig = rFib.fcStshf = nCurPos; 549 m_nStyAnzPos = nCurPos + 2; // Anzahl wird nachgetragen 550 551 if ( m_rWW8Export.bWrtWW8 ) 552 { 553 static sal_uInt8 __READONLY_DATA aStShi[] = { 554 0x12, 0x00, 555 0x0F, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x5B, 0x00, 556 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 557 0x00, 0x00 }; 558 559 m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) ); 560 } 561 else 562 { 563 static sal_uInt8 __READONLY_DATA aStShi[] = { 564 0x0E, 0x00, 565 0x0F, 0x00, 0x08, 0x00, 0x01, 0x00, 0x4B, 0x00, 566 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00 }; 567 m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) ); 568 } 569 } 570 571 void WW8AttributeOutput::EndStyles( sal_uInt16 nNumberOfStyles ) 572 { 573 WW8Fib& rFib = *m_rWW8Export.pFib; 574 575 rFib.lcbStshfOrig = rFib.lcbStshf = m_rWW8Export.pTableStrm->Tell() - rFib.fcStshf; 576 SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, m_nStyAnzPos, nNumberOfStyles ); 577 } 578 579 void MSWordStyles::OutputStylesTable() 580 { 581 m_rExport.bStyDef = true; 582 583 m_rExport.AttrOutput().StartStyles(); 584 585 sal_uInt16 n; 586 for ( n = 0; n < nUsedSlots; n++ ) 587 OutputStyle( pFmtA[n], n ); 588 589 m_rExport.AttrOutput().EndStyles( nUsedSlots ); 590 591 m_rExport.bStyDef = false; 592 } 593 594 /* */ 595 596 //--------------------------------------------------------------------------- 597 // Fonts 598 //--------------------------------------------------------------------------- 599 wwFont::wwFont(const String &rFamilyName, FontPitch ePitch, FontFamily eFamily, 600 rtl_TextEncoding eChrSet, bool bWrtWW8) : mbAlt(false), mbWrtWW8(bWrtWW8), mePitch(ePitch), meFamily(eFamily), meChrSet(eChrSet) 601 { 602 FontMapExport aResult(rFamilyName); 603 msFamilyNm = aResult.msPrimary; 604 msAltNm = aResult.msSecondary; 605 if (msAltNm.Len() && msAltNm != msFamilyNm && 606 (msFamilyNm.Len() + msAltNm.Len() + 2 <= 65) ) 607 { 608 //max size of szFfn in 65 chars 609 mbAlt = true; 610 } 611 612 memset(maWW8_FFN, 0, sizeof(maWW8_FFN)); 613 614 if (bWrtWW8) 615 { 616 maWW8_FFN[0] = (sal_uInt8)( 6 - 1 + 0x22 + ( 2 * ( 1 + msFamilyNm.Len() ) )); 617 if (mbAlt) 618 maWW8_FFN[0] = static_cast< sal_uInt8 >(maWW8_FFN[0] + 2 * ( 1 + msAltNm.Len())); 619 } 620 else 621 { 622 maWW8_FFN[0] = (sal_uInt8)( 6 - 1 + 1 + msFamilyNm.Len() ); 623 if (mbAlt) 624 maWW8_FFN[0] = static_cast< sal_uInt8 >(maWW8_FFN[0] + 1 + msAltNm.Len()); 625 } 626 627 sal_uInt8 aB = 0; 628 switch(ePitch) 629 { 630 case PITCH_VARIABLE: 631 aB |= 2; // aF.prg = 2 632 break; 633 case PITCH_FIXED: 634 aB |= 1; 635 break; 636 default: // aF.prg = 0 : DEFAULT_PITCH (windows.h) 637 break; 638 } 639 aB |= 1 << 2; // aF.fTrueType = 1; weiss ich nicht besser; 640 641 switch(eFamily) 642 { 643 case FAMILY_ROMAN: 644 aB |= 1 << 4; // aF.ff = 1; 645 break; 646 case FAMILY_SWISS: 647 aB |= 2 << 4; // aF.ff = 2; 648 break; 649 case FAMILY_MODERN: 650 aB |= 3 << 4; // aF.ff = 3; 651 break; 652 case FAMILY_SCRIPT: 653 aB |= 4 << 4; // aF.ff = 4; 654 break; 655 case FAMILY_DECORATIVE: 656 aB |= 5 << 4; // aF.ff = 5; 657 break; 658 default: // aF.ff = 0; FF_DONTCARE (windows.h) 659 break; 660 } 661 maWW8_FFN[1] = aB; 662 663 ShortToSVBT16( 400, &maWW8_FFN[2] ); // weiss ich nicht besser 664 // 400 == FW_NORMAL (windows.h) 665 maWW8_FFN[4] = sw::ms::rtl_TextEncodingToWinCharset(eChrSet); 666 667 if (mbAlt) 668 maWW8_FFN[5] = static_cast< sal_uInt8 >(msFamilyNm.Len() + 1); 669 } 670 671 bool wwFont::Write(SvStream *pTableStrm) const 672 { 673 pTableStrm->Write(maWW8_FFN, sizeof(maWW8_FFN)); // fixed part 674 if (mbWrtWW8) 675 { 676 // ab Ver8 sind folgende beiden Felder eingeschoben, 677 // werden von uns ignoriert. 678 //char panose[ 10 ]; // 0x6 PANOSE 679 //char fs[ 24 ]; // 0x10 FONTSIGNATURE 680 SwWW8Writer::FillCount(*pTableStrm, 0x22); 681 SwWW8Writer::WriteString16(*pTableStrm, msFamilyNm, true); 682 if (mbAlt) 683 SwWW8Writer::WriteString16(*pTableStrm, msAltNm, true); 684 } 685 else 686 { 687 SwWW8Writer::WriteString8(*pTableStrm, msFamilyNm, true, 688 RTL_TEXTENCODING_MS_1252); 689 if (mbAlt) 690 { 691 SwWW8Writer::WriteString8( *pTableStrm, msAltNm, true, 692 RTL_TEXTENCODING_MS_1252); 693 } 694 } 695 return true; 696 } 697 698 #ifdef DOCX 699 void wwFont::WriteDocx( const DocxAttributeOutput* rAttrOutput ) const 700 { 701 // no font embedding, panose id, subsetting, ... implemented 702 703 rAttrOutput->StartFont( msFamilyNm ); 704 705 if ( mbAlt ) 706 rAttrOutput->FontAlternateName( msAltNm ); 707 rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ) ); 708 rAttrOutput->FontFamilyType( meFamily ); 709 rAttrOutput->FontPitchType( mePitch ); 710 711 rAttrOutput->EndFont(); 712 } 713 #endif 714 715 void wwFont::WriteRtf( const RtfAttributeOutput* rAttrOutput ) const 716 { 717 rAttrOutput->FontFamilyType( meFamily, *this ); 718 rAttrOutput->FontPitchType( mePitch ); 719 rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ) ); 720 rAttrOutput->StartFont( msFamilyNm ); 721 if ( mbAlt ) 722 rAttrOutput->FontAlternateName( msAltNm ); 723 rAttrOutput->EndFont(); 724 } 725 726 bool operator<(const wwFont &r1, const wwFont &r2) 727 { 728 int nRet = memcmp(r1.maWW8_FFN, r2.maWW8_FFN, sizeof(r1.maWW8_FFN)); 729 if (nRet == 0) 730 { 731 StringCompare eRet = r1.msFamilyNm.CompareTo(r2.msFamilyNm); 732 if (eRet == COMPARE_EQUAL) 733 eRet = r1.msAltNm.CompareTo(r2.msAltNm); 734 nRet = eRet; 735 } 736 return nRet < 0; 737 } 738 739 740 sal_uInt16 wwFontHelper::GetId(const wwFont &rFont) 741 { 742 sal_uInt16 nRet; 743 ::std::map<wwFont, sal_uInt16>::const_iterator aIter = maFonts.find(rFont); 744 if (aIter != maFonts.end()) 745 nRet = aIter->second; 746 else 747 { 748 nRet = static_cast< sal_uInt16 >(maFonts.size()); 749 maFonts[rFont] = nRet; 750 } 751 return nRet; 752 } 753 754 void wwFontHelper::InitFontTable(bool bWrtWW8,const SwDoc& rDoc) 755 { 756 mbWrtWW8 = bWrtWW8; 757 758 GetId(wwFont(CREATE_CONST_ASC("Times New Roman"), PITCH_VARIABLE, 759 FAMILY_ROMAN, RTL_TEXTENCODING_MS_1252,bWrtWW8)); 760 761 GetId(wwFont(CREATE_CONST_ASC("Symbol"), PITCH_VARIABLE, FAMILY_ROMAN, 762 RTL_TEXTENCODING_SYMBOL,bWrtWW8)); 763 764 GetId(wwFont(CREATE_CONST_ASC("Arial"), PITCH_VARIABLE, FAMILY_SWISS, 765 RTL_TEXTENCODING_MS_1252,bWrtWW8)); 766 767 const SvxFontItem* pFont = (const SvxFontItem*)GetDfltAttr(RES_CHRATR_FONT); 768 769 GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(), 770 pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8)); 771 772 const SfxItemPool& rPool = rDoc.GetAttrPool(); 773 if (0 != (pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem(RES_CHRATR_FONT))) 774 { 775 GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(), 776 pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8)); 777 } 778 779 if (!bLoadAllFonts) 780 return; 781 782 const sal_uInt16 aTypes[] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT, 0 }; 783 for (const sal_uInt16* pId = aTypes; *pId; ++pId) 784 { 785 sal_uInt32 const nMaxItem = rPool.GetItemCount2( *pId ); 786 for (sal_uInt32 nGet = 0; nGet < nMaxItem; ++nGet) 787 { 788 pFont = (const SvxFontItem*)rPool.GetItem2( *pId, nGet ); 789 if (0 != pFont) 790 { 791 GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(), 792 pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8)); 793 } 794 } 795 } 796 } 797 798 sal_uInt16 wwFontHelper::GetId(const Font& rFont) 799 { 800 wwFont aFont(rFont.GetName(), rFont.GetPitch(), rFont.GetFamily(), 801 rFont.GetCharSet(), mbWrtWW8); 802 return GetId(aFont); 803 } 804 805 sal_uInt16 wwFontHelper::GetId(const SvxFontItem& rFont) 806 { 807 wwFont aFont(rFont.GetFamilyName(), rFont.GetPitch(), rFont.GetFamily(), 808 rFont.GetCharSet(), mbWrtWW8); 809 return GetId(aFont); 810 } 811 812 ::std::vector< const wwFont* > wwFontHelper::AsVector() const 813 { 814 ::std::vector<const wwFont *> aFontList( maFonts.size() ); 815 816 typedef ::std::map<wwFont, sal_uInt16>::const_iterator myiter; 817 myiter aEnd = maFonts.end(); 818 for ( myiter aIter = maFonts.begin(); aIter != aEnd; ++aIter ) 819 aFontList[aIter->second] = &aIter->first; 820 821 return aFontList; 822 } 823 824 void wwFontHelper::WriteFontTable(SvStream *pTableStream, WW8Fib& rFib) 825 { 826 rFib.fcSttbfffn = pTableStream->Tell(); 827 /* 828 * Reserve some space to fill in the len after we know how big it is 829 */ 830 if (mbWrtWW8) 831 SwWW8Writer::WriteLong(*pTableStream, 0); 832 else 833 SwWW8Writer::WriteShort(*pTableStream, 0); 834 835 /* 836 * Convert from fast insertion map to linear vector in the order that we 837 * want to write. 838 */ 839 ::std::vector<const wwFont *> aFontList( AsVector() ); 840 841 /* 842 * Write them all to pTableStream 843 */ 844 ::std::for_each(aFontList.begin(), aFontList.end(), 845 ::std::bind2nd(::std::mem_fun(&wwFont::Write),pTableStream)); 846 847 /* 848 * Write the position and len in the FIB 849 */ 850 rFib.lcbSttbfffn = pTableStream->Tell() - rFib.fcSttbfffn; 851 if (mbWrtWW8) 852 SwWW8Writer::WriteLong( *pTableStream, rFib.fcSttbfffn, maFonts.size()); 853 else 854 { 855 SwWW8Writer::WriteShort( *pTableStream, rFib.fcSttbfffn, 856 (sal_Int16)rFib.lcbSttbfffn ); 857 } 858 } 859 860 #ifdef DOCX 861 void wwFontHelper::WriteFontTable( const DocxAttributeOutput& rAttrOutput ) 862 { 863 ::std::vector<const wwFont *> aFontList( AsVector() ); 864 865 ::std::for_each( aFontList.begin(), aFontList.end(), 866 ::std::bind2nd( ::std::mem_fun( &wwFont::WriteDocx ), &rAttrOutput ) ); 867 } 868 #endif 869 870 void wwFontHelper::WriteFontTable( const RtfAttributeOutput& rAttrOutput ) 871 { 872 ::std::vector<const wwFont *> aFontList( AsVector() ); 873 874 ::std::for_each( aFontList.begin(), aFontList.end(), 875 ::std::bind2nd( ::std::mem_fun( &wwFont::WriteRtf ), &rAttrOutput ) ); 876 } 877 878 /* */ 879 880 WW8_WrPlc0::WW8_WrPlc0( sal_uLong nOffset ) 881 : aPos( 4, 4 ), nOfs( nOffset ) 882 { 883 } 884 885 void WW8_WrPlc0::Append( sal_uLong nStartCpOrFc ) 886 { 887 aPos.Insert( nStartCpOrFc - nOfs, aPos.Count() ); 888 } 889 890 void WW8_WrPlc0::Write( SvStream& rStrm ) 891 { 892 sal_uInt16 nLen = aPos.Count(); 893 for( sal_uInt16 i = 0; i < nLen; ++i ) 894 { 895 SVBT32 nP; 896 UInt32ToSVBT32( aPos[i], nP ); 897 rStrm.Write( nP, 4 ); 898 } 899 } 900 901 //------------------------------------------------------------------------------ 902 903 /* */ 904 //------------------------------------------------------------------------------ 905 // class MSWordSections : Uebersetzung PageDescs in Sections 906 // behandelt auch Header und Footer 907 //------------------------------------------------------------------------------ 908 909 MSWordSections::MSWordSections( MSWordExportBase& rExport ) 910 : mbDocumentIsProtected( false ), 911 aSects( 4, 4 ) 912 { 913 const SwSectionFmt *pFmt = 0; 914 rExport.pAktPageDesc = &const_cast<const SwDoc *>(rExport.pDoc)->GetPageDesc( 0 ); 915 916 const SfxPoolItem* pI; 917 const SwNode* pNd = rExport.pCurPam->GetCntntNode(); 918 const SfxItemSet* pSet = pNd ? &((SwCntntNode*)pNd)->GetSwAttrSet() : 0; 919 920 sal_uLong nRstLnNum = pSet ? ((SwFmtLineNumber&)pSet->Get( RES_LINENUMBER )).GetStartValue() : 0; 921 922 const SwTableNode* pTblNd = rExport.pCurPam->GetNode()->FindTableNode(); 923 const SwSectionNode* pSectNd; 924 if ( pTblNd ) 925 { 926 pSet = &pTblNd->GetTable().GetFrmFmt()->GetAttrSet(); 927 pNd = pTblNd; 928 } 929 else if ( 0 != ( pSectNd = pNd->FindSectionNode() ) ) 930 { 931 if ( TOX_HEADER_SECTION == pSectNd->GetSection().GetType() && 932 pSectNd->StartOfSectionNode()->IsSectionNode() ) 933 { 934 pSectNd = pSectNd->StartOfSectionNode()->GetSectionNode(); 935 } 936 937 if ( TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() ) 938 { 939 pNd = pSectNd; 940 rExport.pCurPam->GetPoint()->nNode = *pNd; 941 } 942 943 if ( CONTENT_SECTION == pSectNd->GetSection().GetType() ) 944 pFmt = pSectNd->GetSection().GetFmt(); 945 } 946 947 // Hole evtl. Pagedesc des 1. Nodes 948 if ( pSet && 949 SFX_ITEM_ON == pSet->GetItemState( RES_PAGEDESC, true, &pI ) && 950 ( (SwFmtPageDesc*)pI )->GetPageDesc() ) 951 { 952 AppendSection( *(SwFmtPageDesc*)pI, *pNd, pFmt, nRstLnNum ); 953 } 954 else 955 AppendSection( rExport.pAktPageDesc, pFmt, nRstLnNum ); 956 } 957 958 WW8_WrPlcSepx::WW8_WrPlcSepx( MSWordExportBase& rExport ) 959 : MSWordSections( rExport ) 960 , aCps( 4, 4 ) 961 , m_bHeaderFooterWritten(false) 962 , pTxtPos( 0 ) 963 { 964 // to be in sync with the AppendSection() call in the MSWordSections 965 // constructor 966 aCps.Insert( sal_uLong( 0 ), aCps.Count() ); 967 } 968 969 MSWordSections::~MSWordSections() 970 { 971 } 972 973 WW8_WrPlcSepx::~WW8_WrPlcSepx() 974 { 975 delete pTxtPos; 976 } 977 978 bool MSWordSections::HeaderFooterWritten() 979 { 980 return false; // only relevant for WW8 981 } 982 983 bool WW8_WrPlcSepx::HeaderFooterWritten() 984 { 985 return m_bHeaderFooterWritten; 986 } 987 988 sal_uInt16 MSWordSections::CurrentNumberOfColumns( const SwDoc &rDoc ) const 989 { 990 ASSERT( aSects.Count(), "no segement inserted yet" ); 991 if ( !aSects.Count() ) 992 return 1; 993 994 return NumberOfColumns( rDoc, aSects[aSects.Count() - 1] ); 995 } 996 997 sal_uInt16 MSWordSections::NumberOfColumns( const SwDoc &rDoc, const WW8_SepInfo& rInfo ) const 998 { 999 const SwPageDesc* pPd = rInfo.pPageDesc; 1000 if ( !pPd ) 1001 pPd = &rDoc.GetPageDesc( 0 ); 1002 1003 if ( !pPd ) 1004 { 1005 ASSERT( pPd, "totally impossible" ); 1006 return 1; 1007 } 1008 1009 const SfxItemSet &rSet = pPd->GetMaster().GetAttrSet(); 1010 SfxItemSet aSet( *rSet.GetPool(), RES_COL, RES_COL ); 1011 aSet.SetParent( &rSet ); 1012 1013 //0xffffffff, what the hell is going on with that!, fixme most terribly 1014 if ( rInfo.pSectionFmt && (SwSectionFmt*)0xFFFFFFFF != rInfo.pSectionFmt ) 1015 aSet.Put( rInfo.pSectionFmt->GetFmtAttr( RES_COL ) ); 1016 1017 const SwFmtCol& rCol = (const SwFmtCol&)aSet.Get( RES_COL ); 1018 const SwColumns& rColumns = rCol.GetColumns(); 1019 return rColumns.Count(); 1020 } 1021 1022 const WW8_SepInfo* MSWordSections::CurrentSectionInfo() 1023 { 1024 if ( aSects.Count() > 0 ) 1025 return &aSects[aSects.Count() - 1]; 1026 1027 return NULL; 1028 } 1029 1030 void MSWordSections::AppendSection( const SwPageDesc* pPd, 1031 const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo ) 1032 { 1033 if (HeaderFooterWritten()) { 1034 return; // #i117955# prevent new sections in endnotes 1035 } 1036 aSects.Insert( WW8_SepInfo( pPd, pSectionFmt, nLnNumRestartNo ), 1037 aSects.Count() ); 1038 NeedsDocumentProtected( aSects[aSects.Count()-1] ); 1039 } 1040 1041 void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd, 1042 const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo ) 1043 { 1044 if (HeaderFooterWritten()) { 1045 return; // #i117955# prevent new sections in endnotes 1046 } 1047 aCps.Insert( nStartCp, aCps.Count() ); 1048 1049 AppendSection( pPd, pSectionFmt, nLnNumRestartNo ); 1050 } 1051 1052 void MSWordSections::AppendSection( const SwFmtPageDesc& rPD, 1053 const SwNode& rNd, const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo ) 1054 { 1055 if (HeaderFooterWritten()) { 1056 return; // #i117955# prevent new sections in endnotes 1057 } 1058 WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFmt, nLnNumRestartNo, 1059 rPD.GetNumOffset(), &rNd ); 1060 aSects.Insert( aI, aSects.Count() ); 1061 NeedsDocumentProtected( aI ); 1062 } 1063 1064 void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwFmtPageDesc& rPD, 1065 const SwNode& rNd, const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo ) 1066 { 1067 if (HeaderFooterWritten()) { 1068 return; // #i117955# prevent new sections in endnotes 1069 } 1070 aCps.Insert(nStartCp, aCps.Count()); 1071 1072 AppendSection( rPD, rNd, pSectionFmt, nLnNumRestartNo ); 1073 } 1074 1075 // MSWordSections::SetNum() setzt in jeder Section beim 1. Aufruf den 1076 // Num-Pointer, alle folgenden Aufrufe werden ignoriert. Damit wird 1077 // die erste Aufzaehlung einer Section uebernommen. 1078 1079 void MSWordSections::SetNum( const SwTxtNode* pNumNd ) 1080 { 1081 WW8_SepInfo& rInfo = aSects[ aSects.Count() - 1 ]; 1082 if ( !rInfo.pNumNd ) // noch nicht belegt 1083 rInfo.pNumNd = pNumNd; 1084 } 1085 1086 void WW8_WrPlcSepx::WriteFtnEndTxt( WW8Export& rWrt, sal_uLong nCpStt ) 1087 { 1088 sal_uInt8 nInfoFlags = 0; 1089 const SwFtnInfo& rInfo = rWrt.pDoc->GetFtnInfo(); 1090 if( rInfo.aErgoSum.Len() ) nInfoFlags |= 0x02; 1091 if( rInfo.aQuoVadis.Len() ) nInfoFlags |= 0x04; 1092 1093 sal_uInt8 nEmptyStt = rWrt.bWrtWW8 ? 0 : 6; 1094 if( nInfoFlags ) 1095 { 1096 if( rWrt.bWrtWW8 ) 1097 pTxtPos->Append( nCpStt ); // empty footenote separator 1098 1099 if( 0x02 & nInfoFlags ) // Footenote contiunation separator 1100 { 1101 pTxtPos->Append( nCpStt ); 1102 rWrt.WriteStringAsPara( rInfo.aErgoSum ); 1103 rWrt.WriteStringAsPara( aEmptyStr ); 1104 nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1105 } 1106 else if( rWrt.bWrtWW8 ) 1107 pTxtPos->Append( nCpStt ); 1108 1109 if( 0x04 & nInfoFlags ) // Footenote contiunation notice 1110 { 1111 pTxtPos->Append( nCpStt ); 1112 rWrt.WriteStringAsPara( rInfo.aQuoVadis ); 1113 rWrt.WriteStringAsPara( aEmptyStr ); 1114 nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1115 } 1116 else if( rWrt.bWrtWW8 ) 1117 pTxtPos->Append( nCpStt ); 1118 1119 if( rWrt.bWrtWW8 ) 1120 nEmptyStt = 3; 1121 else 1122 rWrt.pDop->grpfIhdt = nInfoFlags; 1123 } 1124 1125 while( 6 > nEmptyStt++ ) 1126 pTxtPos->Append( nCpStt ); 1127 1128 // gleich die Flags am Dop setzen 1129 WW8Dop& rDop = *rWrt.pDop; 1130 // Footnote Info 1131 switch( rInfo.eNum ) 1132 { 1133 case FTNNUM_PAGE: rDop.rncFtn = 2; break; 1134 case FTNNUM_CHAPTER: rDop.rncFtn = 1; break; 1135 default: rDop.rncFtn = 0; break; 1136 } // rncFtn 1137 rDop.nfcFtnRef = WW8Export::GetNumId( rInfo.aFmt.GetNumberingType() ); 1138 rDop.nFtn = rInfo.nFtnOffset + 1; 1139 rDop.fpc = rWrt.bFtnAtTxtEnd ? 2 : 1; 1140 1141 // Endnote Info 1142 rDop.rncEdn = 0; // rncEdn: Don't Restart 1143 const SwEndNoteInfo& rEndInfo = rWrt.pDoc->GetEndNoteInfo(); 1144 rDop.nfcEdnRef = WW8Export::GetNumId( rEndInfo.aFmt.GetNumberingType() ); 1145 rDop.nEdn = rEndInfo.nFtnOffset + 1; 1146 rDop.epc = rWrt.bEndAtTxtEnd ? 3 : 0; 1147 } 1148 1149 void MSWordSections::SetHeaderFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt, 1150 sal_uInt8 nFlag ) 1151 { 1152 const SfxPoolItem* pItem; 1153 if( SFX_ITEM_SET == rFmt.GetItemState(RES_HEADER, true, &pItem) 1154 && ((SwFmtHeader*)pItem)->IsActive() && 1155 ((SwFmtHeader*)pItem)->GetHeaderFmt() ) 1156 rHeadFootFlags |= nFlag; 1157 } 1158 1159 void MSWordSections::SetFooterFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt, 1160 sal_uInt8 nFlag ) 1161 { 1162 const SfxPoolItem* pItem; 1163 if( SFX_ITEM_SET == rFmt.GetItemState(RES_FOOTER, true, &pItem) 1164 && ((SwFmtFooter*)pItem)->IsActive() && 1165 ((SwFmtFooter*)pItem)->GetFooterFmt() ) 1166 rHeadFootFlags |= nFlag; 1167 } 1168 1169 void WW8_WrPlcSepx::OutHeaderFooter( WW8Export& rWrt, bool bHeader, 1170 const SwFmt& rFmt, sal_uLong& rCpPos, sal_uInt8 nHFFlags, 1171 sal_uInt8 nFlag, sal_uInt8 nBreakCode) 1172 { 1173 if ( nFlag & nHFFlags ) 1174 { 1175 pTxtPos->Append( rCpPos ); 1176 rWrt.WriteHeaderFooterText( rFmt, bHeader); 1177 rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW ) 1178 rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1179 } 1180 else if ( rWrt.bWrtWW8 ) 1181 { 1182 pTxtPos->Append( rCpPos ); 1183 if (rWrt.bHasHdr && nBreakCode!=0) 1184 { 1185 rWrt.WriteStringAsPara( aEmptyStr ); // Empty paragraph for empty header/footer 1186 rWrt.WriteStringAsPara( aEmptyStr ); // a CR that WW8 needs for end of the stream 1187 rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1188 } 1189 } 1190 } 1191 1192 void MSWordSections::NeedsDocumentProtected(const WW8_SepInfo &rInfo) 1193 { 1194 if (rInfo.IsProtected()) 1195 mbDocumentIsProtected = true; 1196 } 1197 1198 bool WW8_SepInfo::IsProtected() const 1199 { 1200 bool bRet = false; 1201 if ( 1202 pSectionFmt && 1203 ((SwSectionFmt*)0xFFFFFFFF != pSectionFmt) 1204 ) 1205 { 1206 const SwSection *pSection = pSectionFmt->GetSection(); 1207 if (pSection && pSection->IsProtect()) 1208 { 1209 bRet = true; 1210 } 1211 } 1212 return bRet; 1213 } 1214 1215 1216 void MSWordSections::CheckForFacinPg( WW8Export& rWrt ) const 1217 { 1218 // 2 Werte werden gesetzt 1219 // Dop.fFacingPages == Kopf-/Fusszeilen unterschiedlich 1220 // Dop.fSwapBordersFacingPgs == gespiegelte Raender 1221 for( sal_uInt16 i = 0, nEnde = 0; i < aSects.Count(); ++i ) 1222 { 1223 WW8_SepInfo& rSepInfo = aSects[i]; 1224 if( !rSepInfo.pSectionFmt ) 1225 { 1226 const SwPageDesc* pPd = rSepInfo.pPageDesc; 1227 if( pPd->GetFollow() && pPd != pPd->GetFollow() && 1228 pPd->GetFollow()->GetFollow() == pPd->GetFollow() && 1229 rSepInfo.pPDNd && 1230 pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) ) 1231 // das ist also 1.Seite und nachfolgende, also nur den 1232 // follow beachten 1233 pPd = pPd->GetFollow(); 1234 1235 // left-/right chain of pagedescs ? 1236 else if( !( 1 & nEnde ) && 1237 pPd->GetFollow() && pPd != pPd->GetFollow() && 1238 pPd->GetFollow()->GetFollow() == pPd && 1239 (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) && 1240 nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) || 1241 ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) && 1242 nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) )) 1243 { 1244 rWrt.pDop->fFacingPages = rWrt.pDop->fMirrorMargins = true; 1245 nEnde |= 1; 1246 } 1247 1248 if( !( 1 & nEnde ) && 1249 ( !pPd->IsHeaderShared() || !pPd->IsFooterShared() )) 1250 { 1251 rWrt.pDop->fFacingPages = true; 1252 nEnde |= 1; 1253 } 1254 if( !( 2 & nEnde ) && 1255 nsUseOnPage::PD_MIRROR == ( nsUseOnPage::PD_MIRROR & pPd->ReadUseOn() )) 1256 { 1257 rWrt.pDop->fSwapBordersFacingPgs = 1258 rWrt.pDop->fMirrorMargins = true; 1259 nEnde |= 2; 1260 } 1261 1262 if( 3 == nEnde ) 1263 break; // weiter brauchen wird nicht 1264 } 1265 } 1266 } 1267 1268 int MSWordSections::HasBorderItem( const SwFmt& rFmt ) 1269 { 1270 const SfxPoolItem* pItem; 1271 return SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem) && 1272 ( ((SvxBoxItem*)pItem)->GetTop() || 1273 ((SvxBoxItem*)pItem)->GetBottom() || 1274 ((SvxBoxItem*)pItem)->GetLeft() || 1275 ((SvxBoxItem*)pItem)->GetRight() ); 1276 } 1277 1278 void WW8AttributeOutput::StartSection() 1279 { 1280 m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren 1281 } 1282 1283 void WW8AttributeOutput::SectionFormProtection( bool bProtected ) 1284 { 1285 //If the document is to be exported as protected, then if a segment 1286 //is not protected, set the unlocked flag 1287 if ( m_rWW8Export.pSepx->DocumentIsProtected() && !bProtected ) 1288 { 1289 if ( m_rWW8Export.bWrtWW8 ) 1290 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFProtected ); 1291 else 1292 m_rWW8Export.pO->Insert( 139, m_rWW8Export.pO->Count() ); 1293 m_rWW8Export.pO->Insert( 1 , m_rWW8Export.pO->Count() ); 1294 } 1295 } 1296 1297 void WW8AttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo ) 1298 { 1299 // sprmSNLnnMod - activate Line Numbering and define Modulo 1300 if ( m_rWW8Export.bWrtWW8 ) 1301 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNLnnMod ); 1302 else 1303 m_rWW8Export.pO->Insert( 154, m_rWW8Export.pO->Count() ); 1304 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)rLnNumInfo.GetCountBy() ); 1305 1306 // sprmSDxaLnn - xPosition of Line Number 1307 if ( m_rWW8Export.bWrtWW8 ) 1308 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SDxaLnn ); 1309 else 1310 m_rWW8Export.pO->Insert( 155, m_rWW8Export.pO->Count() ); 1311 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)rLnNumInfo.GetPosFromLeft() ); 1312 1313 // sprmSLnc - restart number: 0 per page, 1 per section, 2 never restart 1314 if ( nRestartNo || !rLnNumInfo.IsRestartEachPage() ) 1315 { 1316 if ( m_rWW8Export.bWrtWW8 ) 1317 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnc ); 1318 else 1319 m_rWW8Export.pO->Insert( 152, m_rWW8Export.pO->Count() ); 1320 m_rWW8Export.pO->Insert( nRestartNo ? 1 : 2, m_rWW8Export.pO->Count() ); 1321 } 1322 1323 // sprmSLnnMin - Restart the Line Number with given value 1324 if ( nRestartNo ) 1325 { 1326 if ( m_rWW8Export.bWrtWW8 ) 1327 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnnMin ); 1328 else 1329 m_rWW8Export.pO->Insert( 160, m_rWW8Export.pO->Count() ); 1330 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)nRestartNo - 1 ); 1331 } 1332 } 1333 1334 void WW8AttributeOutput::SectionTitlePage() 1335 { 1336 // sprmSFTitlePage 1337 if ( m_rWW8Export.bWrtWW8 ) 1338 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFTitlePage ); 1339 else 1340 m_rWW8Export.pO->Insert( 143, m_rWW8Export.pO->Count() ); 1341 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() ); 1342 } 1343 1344 void WW8AttributeOutput::SectionPageBorders( const SwFrmFmt* pPdFmt, const SwFrmFmt* pPdFirstPgFmt ) 1345 { 1346 if ( m_rWW8Export.bWrtWW8 ) // Seitenumrandung schreiben 1347 { 1348 sal_uInt16 nPgBorder = MSWordSections::HasBorderItem( *pPdFmt ) ? 0 : USHRT_MAX; 1349 if ( pPdFmt != pPdFirstPgFmt ) 1350 { 1351 if ( MSWordSections::HasBorderItem( *pPdFirstPgFmt ) ) 1352 { 1353 if ( USHRT_MAX == nPgBorder ) 1354 { 1355 nPgBorder = 1; 1356 // nur die 1. Seite umrandet -> BoxItem aus dem 1357 // richtigen Format besorgen 1358 m_rWW8Export.pISet = &pPdFirstPgFmt->GetAttrSet(); 1359 OutputItem( pPdFirstPgFmt->GetFmtAttr( RES_BOX ) ); 1360 } 1361 } 1362 else if ( !nPgBorder ) 1363 nPgBorder = 2; 1364 } 1365 1366 if ( USHRT_MAX != nPgBorder ) 1367 { 1368 // Flag und das Border Attribut schreiben 1369 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgbProp ); 1370 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPgBorder ); 1371 } 1372 } 1373 } 1374 1375 void WW8AttributeOutput::SectionBiDi( bool bBiDi ) 1376 { 1377 if ( m_rWW8Export.bWrtWW8 ) 1378 { 1379 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFBiDi ); 1380 m_rWW8Export.pO->Insert( bBiDi? 1: 0, m_rWW8Export.pO->Count() ); 1381 } 1382 } 1383 1384 void WW8AttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber ) 1385 { 1386 // sprmSNfcPgn 1387 sal_uInt8 nb = WW8Export::GetNumId( nNumType ); 1388 if ( m_rWW8Export.bWrtWW8 ) 1389 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNfcPgn ); 1390 else 1391 m_rWW8Export.pO->Insert( 147, m_rWW8Export.pO->Count() ); 1392 m_rWW8Export.pO->Insert( nb, m_rWW8Export.pO->Count() ); 1393 1394 if ( nPageRestartNumber ) 1395 { 1396 // sprmSFPgnRestart 1397 if ( m_rWW8Export.bWrtWW8 ) 1398 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFPgnRestart ); 1399 else 1400 m_rWW8Export.pO->Insert( 150, m_rWW8Export.pO->Count() ); 1401 m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() ); 1402 1403 // sprmSPgnStart 1404 if ( m_rWW8Export.bWrtWW8 ) 1405 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgnStart ); 1406 else 1407 m_rWW8Export.pO->Insert( 161, m_rWW8Export.pO->Count() ); 1408 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPageRestartNumber ); 1409 } 1410 } 1411 1412 void WW8AttributeOutput::SectionType( sal_uInt8 nBreakCode ) 1413 { 1414 if ( 2 != nBreakCode ) // new page is the default 1415 { 1416 if ( m_rWW8Export.bWrtWW8 ) 1417 SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SBkc ); 1418 else 1419 m_rWW8Export.pO->Insert( 142, m_rWW8Export.pO->Count() ); 1420 m_rWW8Export.pO->Insert( nBreakCode, m_rWW8Export.pO->Count() ); 1421 } 1422 } 1423 1424 void WW8AttributeOutput::SectionWW6HeaderFooterFlags( sal_uInt8 nHeadFootFlags ) 1425 { 1426 if ( nHeadFootFlags && !m_rWW8Export.bWrtWW8 ) 1427 { 1428 sal_uInt8 nTmpFlags = nHeadFootFlags; 1429 if ( m_rWW8Export.pDop->fFacingPages ) 1430 { 1431 if ( !(nTmpFlags & WW8_FOOTER_EVEN) && (nTmpFlags & WW8_FOOTER_ODD ) ) 1432 nTmpFlags |= WW8_FOOTER_EVEN; 1433 1434 if ( !(nTmpFlags & WW8_HEADER_EVEN) && (nTmpFlags & WW8_HEADER_ODD ) ) 1435 nTmpFlags |= WW8_HEADER_EVEN; 1436 } 1437 1438 // sprmSGprfIhdt, wird nur noch im WW95 benoetigt 1439 m_rWW8Export.pO->Insert( 153, m_rWW8Export.pO->Count() ); 1440 m_rWW8Export.pO->Insert( nTmpFlags, m_rWW8Export.pO->Count() ); 1441 } 1442 } 1443 1444 void WW8Export::SetupSectionPositions( WW8_PdAttrDesc* pA ) 1445 { 1446 if ( !pA ) 1447 return; 1448 1449 if (pO->Count()) // are there attributes? 1450 { 1451 pA->m_nLen = pO->Count(); 1452 pA->m_pData.reset(new sal_uInt8[pO->Count()]); 1453 // store for later 1454 memcpy( pA->m_pData.get(), pO->GetData(), pO->Count() ); 1455 pO->Remove( 0, pO->Count() ); // leeren fuer HdFt-Text 1456 } 1457 else 1458 { 1459 pA->m_pData.reset(); 1460 pA->m_nLen = 0; 1461 } 1462 } 1463 1464 void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags, 1465 const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 nBreakCode ) 1466 { 1467 sal_uLong nCpPos = Fc2Cp( Strm().Tell() ); 1468 1469 IncrementHdFtIndex(); 1470 if ( !(nHeadFootFlags & WW8_HEADER_EVEN) && pDop->fFacingPages ) 1471 pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode ); 1472 else 1473 pSepx->OutHeaderFooter( *this, true, rLeftFmt, nCpPos, nHeadFootFlags, WW8_HEADER_EVEN, nBreakCode ); 1474 IncrementHdFtIndex(); 1475 pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode ); 1476 1477 IncrementHdFtIndex(); 1478 if ( !(nHeadFootFlags & WW8_FOOTER_EVEN) && pDop->fFacingPages ) 1479 pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode ); 1480 else 1481 pSepx->OutHeaderFooter( *this, false, rLeftFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_EVEN, nBreakCode ); 1482 IncrementHdFtIndex(); 1483 pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode ); 1484 1485 //#i24344# Drawing objects cannot be directly shared between main hd/ft 1486 //and title hd/ft so we need to differenciate them 1487 IncrementHdFtIndex(); 1488 pSepx->OutHeaderFooter( *this, true, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_HEADER_FIRST, nBreakCode ); 1489 pSepx->OutHeaderFooter( *this, false, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_FIRST, nBreakCode ); 1490 } 1491 1492 void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAttrDesc* pA ) 1493 { 1494 const SwPageDesc* pPd = rSepInfo.pPageDesc; 1495 1496 if ( rSepInfo.pSectionFmt && !pPd ) 1497 pPd = &const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 ); 1498 1499 pAktPageDesc = pPd; 1500 1501 if ( !pPd ) 1502 return; 1503 1504 bool bOldPg = bOutPageDescs; 1505 bOutPageDescs = true; 1506 1507 AttrOutput().StartSection(); 1508 1509 // forms 1510 AttrOutput().SectionFormProtection( rSepInfo.IsProtected() ); 1511 1512 // line numbers 1513 const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo(); 1514 if ( rLnNumInfo.IsPaintLineNumbers() ) 1515 AttrOutput().SectionLineNumbering( rSepInfo.nLnNumRestartNo, rLnNumInfo ); 1516 1517 /* sprmSBkc, break code: 0 No break, 1 New column 1518 2 New page, 3 Even page, 4 Odd page 1519 */ 1520 sal_uInt8 nBreakCode = 2; // default neue Seite beginnen 1521 bool bOutPgDscSet = true, bLeftRightPgChain = false; 1522 const SwFrmFmt* pPdFmt = &pPd->GetMaster(); 1523 const SwFrmFmt* pPdFirstPgFmt = pPdFmt; 1524 if ( rSepInfo.pSectionFmt ) 1525 { 1526 // ist pSectionFmt gesetzt, dann gab es einen SectionNode 1527 // gueltiger Pointer -> Section beginnt, 1528 // 0xfff -> Section wird beendet 1529 nBreakCode = 0; // fortlaufender Abschnitt 1530 1531 if ( rSepInfo.pPDNd && rSepInfo.pPDNd->IsCntntNode() ) 1532 { 1533 if ( !NoPageBreakSection( &rSepInfo.pPDNd->GetCntntNode()->GetSwAttrSet() ) ) 1534 { 1535 nBreakCode = 2; 1536 } 1537 } 1538 1539 if ( (SwSectionFmt*)0xFFFFFFFF != rSepInfo.pSectionFmt ) 1540 { 1541 if ( nBreakCode == 0 ) 1542 bOutPgDscSet = false; 1543 1544 // Itemset erzeugen, das das PgDesk-AttrSet beerbt: 1545 // als Nachkomme wird bei 'deep'-OutputItemSet 1546 // auch der Vorfahr abgeklappert 1547 const SfxItemSet* pPdSet = &pPdFmt->GetAttrSet(); 1548 SfxItemSet aSet( *pPdSet->GetPool(), pPdSet->GetRanges() ); 1549 aSet.SetParent( pPdSet ); 1550 1551 // am Nachkommen NUR die Spaltigkeit gemaess Sect-Attr. 1552 // umsetzen 1553 1554 const SvxLRSpaceItem &rSectionLR = 1555 ItemGet<SvxLRSpaceItem>( *(rSepInfo.pSectionFmt), RES_LR_SPACE ); 1556 const SvxLRSpaceItem &rPageLR = 1557 ItemGet<SvxLRSpaceItem>( *pPdFmt, RES_LR_SPACE ); 1558 1559 SvxLRSpaceItem aResultLR( rPageLR.GetLeft() + 1560 rSectionLR.GetLeft(), rPageLR.GetRight() + 1561 rSectionLR.GetRight(), 0, 0, RES_LR_SPACE ); 1562 //i120133: The Section width should consider section indent value. 1563 if (rSectionLR.GetLeft()+rSectionLR.GetRight()!=0) 1564 { 1565 const SwFmtCol& rCol = dynamic_cast<const SwFmtCol&>(rSepInfo.pSectionFmt->GetFmtAttr(RES_COL)); 1566 SwFmtCol aCol(rCol); 1567 aCol.SetAdjustValue(rSectionLR.GetLeft()+rSectionLR.GetRight()); 1568 aSet.Put(aCol); 1569 } 1570 else 1571 aSet.Put(rSepInfo.pSectionFmt->GetFmtAttr(RES_COL)); 1572 1573 1574 aSet.Put( aResultLR ); 1575 1576 // und raus damit ins WW-File 1577 const SfxItemSet* pOldI = pISet; 1578 pISet = &aSet; 1579 // --> OD 2007-06-12 #TESTING# 1580 // Switch off test on default item values, if page description 1581 // set (value of <bOutPgDscSet>) isn't written. 1582 AttrOutput().OutputStyleItemSet( aSet, true, bOutPgDscSet ); 1583 // <-- 1584 1585 //Cannot export as normal page framedir, as continous sections 1586 //cannot contain any grid settings like proper sections 1587 AttrOutput().SectionBiDi( FRMDIR_HORI_RIGHT_TOP == TrueFrameDirection( *rSepInfo.pSectionFmt ) ); 1588 1589 pISet = pOldI; 1590 } 1591 } 1592 1593 if ( bOutPgDscSet ) 1594 { 1595 // es ist ein Follow gesetzt und dieser zeigt nicht auf sich 1596 // selbst, so liegt eine Seitenverkettung vor. 1597 // Falls damit eine "Erste Seite" simuliert werden soll, so 1598 // koennen wir das auch als solches schreiben. 1599 // Anders sieht es mit Links/Rechts wechseln aus. Dafuer muss 1600 // erkannt werden, wo der Seitenwechsel statt findet. Hier ist 1601 // es aber dafuer zuspaet! 1602 if ( pPd->GetFollow() && pPd != pPd->GetFollow() && 1603 pPd->GetFollow()->GetFollow() == pPd->GetFollow() && 1604 ( !rSepInfo.pPDNd || pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) ) ) 1605 { 1606 const SwPageDesc *pFollow = pPd->GetFollow(); 1607 const SwFrmFmt& rFollowFmt = pFollow->GetMaster(); 1608 const sal_Int8 nType = pDoc->GetDocumentType(); 1609 if ( sw::util::IsPlausableSingleWordSection( *pPdFmt, rFollowFmt, nType )) 1610 { 1611 if (rSepInfo.pPDNd) 1612 pPdFirstPgFmt = pPd->GetPageFmtOfNode( *rSepInfo.pPDNd ); 1613 else 1614 pPdFirstPgFmt = &pPd->GetMaster(); 1615 1616 pAktPageDesc = pPd = pFollow; 1617 pPdFmt = &rFollowFmt; 1618 1619 // has different headers/footers for the title page 1620 AttrOutput().SectionTitlePage(); 1621 } 1622 } 1623 1624 const SfxItemSet* pOldI = pISet; 1625 1626 AttrOutput().SectionPageBorders( pPdFmt, pPdFirstPgFmt ); 1627 1628 const SfxPoolItem* pItem; 1629 if ( pPdFmt != pPdFirstPgFmt && SFX_ITEM_SET == 1630 pPdFirstPgFmt->GetItemState( RES_PAPER_BIN, true, &pItem ) ) 1631 { 1632 pISet = &pPdFirstPgFmt->GetAttrSet(); 1633 bOutFirstPage = true; 1634 AttrOutput().OutputItem( *pItem ); 1635 bOutFirstPage = false; 1636 } 1637 1638 1639 // left-/right chain of pagedescs ? 1640 if ( pPd->GetFollow() && pPd != pPd->GetFollow() && 1641 pPd->GetFollow()->GetFollow() == pPd && 1642 (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) && 1643 nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) || 1644 ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) && 1645 nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) )) 1646 { 1647 bLeftRightPgChain = true; 1648 1649 // welches ist der Bezugspunkt ????? (links oder rechts?) 1650 // annahme die rechte Seite! 1651 if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) ) 1652 { 1653 nBreakCode = 3; 1654 pPd = pPd->GetFollow(); 1655 pPdFmt = &pPd->GetMaster(); 1656 } 1657 else 1658 nBreakCode = 4; 1659 } 1660 1661 pISet = &pPdFmt->GetAttrSet(); 1662 AttrOutput().OutputStyleItemSet( pPdFmt->GetAttrSet(), true, false ); 1663 pISet = pOldI; 1664 1665 // dann noch die restlichen Einstellungen aus dem PageDesc 1666 1667 AttrOutput().SectionPageNumbering( pPd->GetNumType().GetNumberingType(), rSepInfo.nPgRestartNo ); 1668 1669 // werden es nur linke oder nur rechte Seiten? 1670 if ( 2 == nBreakCode ) 1671 { 1672 if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) ) 1673 nBreakCode = 3; 1674 else if ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) ) 1675 nBreakCode = 4; 1676 } 1677 } 1678 1679 AttrOutput().SectionType( nBreakCode ); 1680 1681 const SwTxtNode* pNd = rSepInfo.pNumNd; 1682 if ( pNd ) 1683 { 1684 const SwNumRule* pRule = pNd->GetNumRule(); 1685 if ( pRule ) 1686 OutputOlst( *pRule ); 1687 } 1688 1689 // Header oder Footer 1690 sal_uInt8 nHeadFootFlags = 0; 1691 1692 const SwFrmFmt* pPdLeftFmt = bLeftRightPgChain 1693 ? &pPd->GetFollow()->GetMaster() 1694 : &pPd->GetLeft(); 1695 1696 if ( nBreakCode != 0 ) 1697 { 1698 MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFmt, WW8_HEADER_ODD ); 1699 MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFmt, WW8_FOOTER_ODD ); 1700 1701 if ( !pPd->IsHeaderShared() || bLeftRightPgChain ) 1702 MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftFmt, WW8_HEADER_EVEN ); 1703 1704 if ( !pPd->IsFooterShared() || bLeftRightPgChain ) 1705 MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFmt, WW8_FOOTER_EVEN ); 1706 1707 if ( pPdFmt != pPdFirstPgFmt ) 1708 { 1709 // es gibt eine ErsteSeite: 1710 MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_HEADER_FIRST ); 1711 MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_FOOTER_FIRST ); 1712 } 1713 1714 AttrOutput().SectionWW6HeaderFooterFlags( nHeadFootFlags ); 1715 } 1716 1717 // binary filters only 1718 SetupSectionPositions( pA ); 1719 1720 /* 1721 !!!!!!!!!!! 1722 // Umrandungen an Kopf- und Fusstexten muessten etwa so gehen: 1723 // Dabei muss etwas wie pOut eingebaut werden, 1724 // das bei jeder Spezialtext-Zeile wiederholt wird. 1725 const SwFrmFmt* pFFmt = rFt.GetFooterFmt(); 1726 const SvxBoxItem& rBox = pFFmt->GetBox(false); 1727 OutWW8_SwFmtBox1( m_rWW8Export.pOut, rBox, false); 1728 !!!!!!!!!!! 1729 Man koennt daraus Absatzattribute machen, die dann bei jedem Absatz 1730 beachtet werden. Gilt fuer Hintergrund/Umrandung 1731 !!!!!!!!!!! 1732 */ 1733 1734 const SwTxtNode *pOldPageRoot = GetHdFtPageRoot(); 1735 SetHdFtPageRoot( rSepInfo.pPDNd ? rSepInfo.pPDNd->GetTxtNode() : 0 ); 1736 1737 WriteHeadersFooters( nHeadFootFlags, *pPdFmt, *pPdLeftFmt, *pPdFirstPgFmt, nBreakCode ); 1738 1739 SetHdFtPageRoot( pOldPageRoot ); 1740 1741 AttrOutput().EndSection(); 1742 1743 // outside of the section properties again 1744 bOutPageDescs = bOldPg; 1745 } 1746 1747 bool WW8_WrPlcSepx::WriteKFTxt( WW8Export& rWrt ) 1748 { 1749 sal_uLong nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1750 1751 ASSERT( !pTxtPos, "wer hat den Pointer gesetzt?" ); 1752 pTxtPos = new WW8_WrPlc0( nCpStart ); 1753 1754 WriteFtnEndTxt( rWrt, nCpStart ); 1755 CheckForFacinPg( rWrt ); 1756 1757 unsigned int nOldIndex = rWrt.GetHdFtIndex(); 1758 rWrt.SetHdFtIndex( 0 ); 1759 // FIXME: this writes the section properties, but not of all sections; 1760 // it's possible that later in the document (e.g. in endnotes) sections 1761 // are added, but they won't have their properties written here! 1762 m_bHeaderFooterWritten = true; 1763 for ( sal_uInt16 i = 0; i < aSects.Count(); ++i ) 1764 { 1765 ::boost::shared_ptr<WW8_PdAttrDesc> const pAttrDesc(new WW8_PdAttrDesc); 1766 m_SectionAttributes.push_back(pAttrDesc); 1767 1768 WW8_SepInfo& rSepInfo = aSects[i]; 1769 rWrt.SectionProperties( rSepInfo, pAttrDesc.get() ); 1770 } 1771 rWrt.SetHdFtIndex( nOldIndex ); //0 1772 1773 if ( pTxtPos->Count() ) 1774 { 1775 // HdFt vorhanden ? 1776 sal_uLong nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1777 pTxtPos->Append( nCpEnd ); // Ende letzter Hd/Ft fuer PlcfHdd 1778 1779 if ( nCpEnd > nCpStart ) 1780 { 1781 ++nCpEnd; 1782 pTxtPos->Append( nCpEnd + 1 ); // Ende letzter Hd/Ft fuer PlcfHdd 1783 1784 rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW ) 1785 } 1786 rWrt.pFldHdFt->Finish( nCpEnd, rWrt.pFib->ccpText + rWrt.pFib->ccpFtn ); 1787 rWrt.pFib->ccpHdr = nCpEnd - nCpStart; 1788 } 1789 else 1790 delete pTxtPos, pTxtPos = 0; 1791 1792 return rWrt.pFib->ccpHdr != 0; 1793 } 1794 1795 void WW8_WrPlcSepx::WriteSepx( SvStream& rStrm ) const 1796 { 1797 OSL_ENSURE(m_SectionAttributes.size() == static_cast<size_t>(aSects.Count()) 1798 , "WriteSepx(): arrays out of sync!"); 1799 for (size_t i = 0; i < m_SectionAttributes.size(); i++) // all sections 1800 { 1801 WW8_PdAttrDesc *const pA = m_SectionAttributes[i].get(); 1802 if (pA->m_nLen && pA->m_pData != NULL) 1803 { 1804 SVBT16 nL; 1805 pA->m_nSepxFcPos = rStrm.Tell(); 1806 ShortToSVBT16( pA->m_nLen, nL ); 1807 rStrm.Write( nL, 2 ); 1808 rStrm.Write( pA->m_pData.get(), pA->m_nLen ); 1809 } 1810 } 1811 } 1812 1813 void WW8_WrPlcSepx::WritePlcSed( WW8Export& rWrt ) const 1814 { 1815 OSL_ENSURE(m_SectionAttributes.size() == static_cast<size_t>(aSects.Count()) 1816 , "WritePlcSed(): arrays out of sync!"); 1817 ASSERT( aCps.Count() == aSects.Count() + 1, "WrPlcSepx: DeSync" ); 1818 sal_uLong nFcStart = rWrt.pTableStrm->Tell(); 1819 1820 sal_uInt16 i; 1821 // ( ueber alle Sections ) 1822 for( i = 0; i <= aSects.Count(); i++ ) 1823 { 1824 sal_uInt32 nP = aCps[i]; 1825 SVBT32 nPos; 1826 UInt32ToSVBT32( nP, nPos ); 1827 rWrt.pTableStrm->Write( nPos, 4 ); 1828 } 1829 1830 static WW8_SED aSed = {{4, 0},{0, 0, 0, 0},{0, 0},{0xff, 0xff, 0xff, 0xff}}; 1831 1832 // ( ueber alle Sections ) 1833 for (size_t j = 0; j < m_SectionAttributes.size(); j++ ) 1834 { 1835 // Sepx-Pos 1836 UInt32ToSVBT32( m_SectionAttributes[j]->m_nSepxFcPos, aSed.fcSepx ); 1837 rWrt.pTableStrm->Write( &aSed, sizeof( aSed ) ); 1838 } 1839 rWrt.pFib->fcPlcfsed = nFcStart; 1840 rWrt.pFib->lcbPlcfsed = rWrt.pTableStrm->Tell() - nFcStart; 1841 } 1842 1843 1844 void WW8_WrPlcSepx::WritePlcHdd( WW8Export& rWrt ) const 1845 { 1846 if( pTxtPos && pTxtPos->Count() ) 1847 { 1848 rWrt.pFib->fcPlcfhdd = rWrt.pTableStrm->Tell(); 1849 pTxtPos->Write( *rWrt.pTableStrm ); // Plc0 1850 rWrt.pFib->lcbPlcfhdd = rWrt.pTableStrm->Tell() - 1851 rWrt.pFib->fcPlcfhdd; 1852 } 1853 } 1854 1855 void MSWordExportBase::WriteHeaderFooterText( const SwFmt& rFmt, bool bHeader ) 1856 { 1857 const SwFmtCntnt *pCntnt; 1858 if ( bHeader ) 1859 { 1860 bHasHdr = true; 1861 const SwFmtHeader& rHd = rFmt.GetHeader(); 1862 ASSERT( rHd.GetHeaderFmt(), "Header text is not here" ); 1863 pCntnt = &rHd.GetHeaderFmt()->GetCntnt(); 1864 } 1865 else 1866 { 1867 bHasFtr = true; 1868 const SwFmtFooter& rFt = rFmt.GetFooter(); 1869 ASSERT( rFt.GetFooterFmt(), "Footer text is not here" ); 1870 pCntnt = &rFt.GetFooterFmt()->GetCntnt(); 1871 } 1872 1873 const SwNodeIndex* pSttIdx = pCntnt->GetCntntIdx(); 1874 1875 if ( pSttIdx ) 1876 { 1877 SwNodeIndex aIdx( *pSttIdx, 1 ), 1878 aEnd( *pSttIdx->GetNode().EndOfSectionNode() ); 1879 sal_uLong nStart = aIdx.GetIndex(); 1880 sal_uLong nEnd = aEnd.GetIndex(); 1881 1882 // Bereich also gueltiger Node 1883 if ( nStart < nEnd ) 1884 { 1885 bool bOldKF = bOutKF; 1886 bOutKF = true; 1887 WriteSpecialText( nStart, nEnd, TXT_HDFT ); 1888 bOutKF = bOldKF; 1889 } 1890 else 1891 pSttIdx = 0; 1892 } 1893 1894 if ( !pSttIdx ) 1895 { 1896 // es gibt keine Kopf-/Fusszeile, aber ein CR ist immer noch noetig 1897 ASSERT( pSttIdx, "K/F-Text nicht richtig da" ); 1898 AttrOutput().EmptyParagraph(); // CR ans Ende ( sonst mault WW ) 1899 } 1900 } 1901 1902 /* */ 1903 //------------------------------------------------------------------------------ 1904 // class WW8_WrPlcFtnEdn : Sammeln der Fuss/Endnoten und Ausgeben der Texte 1905 // und Plcs am Ende des Docs. 1906 // WW8_WrPlcFtnEdn ist die Klasse fuer Fuss- und Endnoten 1907 //------------------------------------------------------------------------------ 1908 WW8_WrPlcSubDoc::WW8_WrPlcSubDoc() 1909 : aCps( 0, 16 ), aCntnt( 0, 16 ), pTxtPos( 0 ) 1910 { 1911 } 1912 1913 WW8_WrPlcSubDoc::~WW8_WrPlcSubDoc() 1914 { 1915 delete pTxtPos; 1916 } 1917 1918 void WW8_WrPlcFtnEdn::Append( WW8_CP nCp, const SwFmtFtn& rFtn ) 1919 { 1920 aCps.Insert( nCp, aCps.Count() ); 1921 void* p = (void*)&rFtn; 1922 aCntnt.Insert( p, aCntnt.Count() ); 1923 } 1924 1925 WW8_Annotation::WW8_Annotation(const SwPostItField* pPostIt) 1926 { 1927 mpRichText = pPostIt->GetTextObject(); 1928 if (!mpRichText) 1929 msSimpleText = pPostIt->GetTxt(); 1930 msOwner = pPostIt->GetPar1(); 1931 maDateTime = DateTime(pPostIt->GetDate(), pPostIt->GetTime()); 1932 } 1933 1934 WW8_Annotation::WW8_Annotation(const SwRedlineData* pRedline) : mpRichText(0) 1935 { 1936 msSimpleText = pRedline->GetComment(); 1937 msOwner = SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor()); 1938 maDateTime = pRedline->GetTimeStamp(); 1939 } 1940 1941 void WW8_WrPlcAnnotations::Append( WW8_CP nCp, const SwPostItField *pPostIt ) 1942 { 1943 aCps.Insert( nCp, aCps.Count() ); 1944 WW8_Annotation* p = new WW8_Annotation(pPostIt); 1945 aCntnt.Insert( p, aCntnt.Count() ); 1946 } 1947 1948 void WW8_WrPlcAnnotations::Append( WW8_CP nCp, const SwRedlineData *pRedline ) 1949 { 1950 maProcessedRedlines.insert(pRedline); 1951 aCps.Insert( nCp, aCps.Count() ); 1952 WW8_Annotation* p = new WW8_Annotation(pRedline); 1953 aCntnt.Insert( p, aCntnt.Count() ); 1954 } 1955 1956 bool WW8_WrPlcAnnotations::IsNewRedlineComment( const SwRedlineData *pRedline ) 1957 { 1958 return maProcessedRedlines.find(pRedline) == maProcessedRedlines.end(); 1959 } 1960 1961 WW8_WrPlcAnnotations::~WW8_WrPlcAnnotations() 1962 { 1963 for( sal_uInt16 n=0; n < aCntnt.Count(); n++ ) 1964 delete (WW8_Annotation*)aCntnt[n]; 1965 } 1966 1967 bool WW8_WrPlcSubDoc::WriteGenericTxt( WW8Export& rWrt, sal_uInt8 nTTyp, 1968 WW8_CP& rCount ) 1969 { 1970 sal_uInt16 nLen = aCntnt.Count(); 1971 if ( !nLen ) 1972 return false; 1973 1974 sal_uLong nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 1975 pTxtPos = new WW8_WrPlc0( nCpStart ); 1976 sal_uInt16 i; 1977 1978 switch ( nTTyp ) 1979 { 1980 case TXT_ATN: 1981 for ( i = 0; i < nLen; i++ ) 1982 { 1983 // Anfaenge fuer PlcfAtnTxt 1984 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() )); 1985 1986 rWrt.WritePostItBegin(); 1987 const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i]; 1988 if (rAtn.mpRichText) 1989 rWrt.WriteOutliner(*rAtn.mpRichText, nTTyp); 1990 else 1991 { 1992 String sTxt(rAtn.msSimpleText); 1993 sTxt.SearchAndReplaceAll(0x0A, 0x0B); 1994 rWrt.WriteStringAsPara( sTxt ); 1995 } 1996 } 1997 break; 1998 1999 case TXT_TXTBOX: 2000 case TXT_HFTXTBOX: 2001 for ( i = 0; i < nLen; i++ ) 2002 { 2003 // textbox - content 2004 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 2005 aCps.Insert( nCP, i ); 2006 pTxtPos->Append( nCP ); 2007 2008 if( aCntnt[ i ] != NULL ) 2009 { 2010 // is it an writer or sdr - textbox? 2011 const SdrObject& rObj = *(SdrObject*)aCntnt[ i ]; 2012 if (rObj.GetObjInventor() == FmFormInventor) 2013 { 2014 sal_uInt8 nOldTyp = rWrt.nTxtTyp; 2015 rWrt.nTxtTyp = nTTyp; 2016 rWrt.GetOCXExp().ExportControl(rWrt,&rObj); 2017 rWrt.nTxtTyp = nOldTyp; 2018 } 2019 else if( rObj.ISA( SdrTextObj ) ) 2020 rWrt.WriteSdrTextObj(rObj, nTTyp); 2021 else 2022 { 2023 const SwFrmFmt* pFmt = ::FindFrmFmt( &rObj ); 2024 ASSERT( pFmt, "wo ist das Format geblieben?" ); 2025 2026 const SwNodeIndex* pNdIdx = pFmt->GetCntnt().GetCntntIdx(); 2027 ASSERT( pNdIdx, "wo ist der StartNode der Textbox?" ); 2028 rWrt.WriteSpecialText( pNdIdx->GetIndex() + 1, 2029 pNdIdx->GetNode().EndOfSectionIndex(), 2030 nTTyp ); 2031 // --> OD 2008-08-07 #156757# 2032 { 2033 SwNodeIndex aContentIdx = *pNdIdx; 2034 aContentIdx++; 2035 if ( aContentIdx.GetNode().IsTableNode() ) 2036 { 2037 bool bContainsOnlyTables = true; 2038 do { 2039 aContentIdx = *(aContentIdx.GetNode().EndOfSectionNode()); 2040 aContentIdx++; 2041 if ( !aContentIdx.GetNode().IsTableNode() && 2042 aContentIdx.GetIndex() != pNdIdx->GetNode().EndOfSectionIndex() ) 2043 { 2044 bContainsOnlyTables = false; 2045 } 2046 } while ( aContentIdx.GetNode().IsTableNode() ); 2047 if ( bContainsOnlyTables ) 2048 { 2049 // Additional paragraph containing a space to 2050 // assure that by WW created RTF from written WW8 2051 // does not crash WW. 2052 rWrt.WriteStringAsPara( String::CreateFromAscii( " " ) ); 2053 } 2054 } 2055 } 2056 // <-- 2057 } 2058 } 2059 else if( i < aSpareFmts.Count() ) 2060 { 2061 if( const SwFrmFmt* pFmt = (const SwFrmFmt*)aSpareFmts[ i ] ) 2062 { 2063 const SwNodeIndex* pNdIdx = pFmt->GetCntnt().GetCntntIdx(); 2064 rWrt.WriteSpecialText( pNdIdx->GetIndex() + 1, 2065 pNdIdx->GetNode().EndOfSectionIndex(), nTTyp ); 2066 } 2067 } 2068 2069 // CR at end of one textbox text ( otherwise WW gpft :-( ) 2070 rWrt.WriteStringAsPara( aEmptyStr ); 2071 } 2072 break; 2073 2074 case TXT_EDN: 2075 case TXT_FTN: 2076 for ( i = 0; i < nLen; i++ ) 2077 { 2078 // Anfaenge fuer PlcfFtnTxt/PlcfEdnTxt 2079 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() )); 2080 2081 // Noten-Inhalt 2082 const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ]; 2083 rWrt.WriteFtnBegin( *pFtn ); 2084 const SwNodeIndex* pIdx = pFtn->GetTxtFtn()->GetStartNode(); 2085 ASSERT( pIdx, "wo ist der StartNode der Fuss-/EndNote?" ); 2086 rWrt.WriteSpecialText( pIdx->GetIndex() + 1, 2087 pIdx->GetNode().EndOfSectionIndex(), 2088 nTTyp ); 2089 } 2090 break; 2091 2092 default: 2093 ASSERT( !this, "was ist das fuer ein SubDocType?" ); 2094 } 2095 2096 pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() )); 2097 // CR ans Ende ( sonst mault WW ) 2098 rWrt.WriteStringAsPara( aEmptyStr ); 2099 2100 WW8_CP nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() ); 2101 pTxtPos->Append( nCpEnd ); 2102 rCount = nCpEnd - nCpStart; 2103 2104 return ( rCount != 0 ); 2105 } 2106 2107 void WW8_WrPlcSubDoc::WriteGenericPlc( WW8Export& rWrt, sal_uInt8 nTTyp, 2108 WW8_FC& rTxtStart, sal_Int32& rTxtCount, WW8_FC& rRefStart, sal_Int32& rRefCount ) const 2109 { 2110 typedef ::std::vector<String>::iterator myiter; 2111 2112 sal_uLong nFcStart = rWrt.pTableStrm->Tell(); 2113 sal_uInt16 nLen = aCps.Count(); 2114 if ( !nLen ) 2115 return; 2116 2117 ASSERT( aCps.Count() + 2 == pTxtPos->Count(), "WritePlc: DeSync" ); 2118 2119 ::std::vector<String> aStrArr; 2120 WW8Fib& rFib = *rWrt.pFib; // n+1-te CP-Pos nach Handbuch 2121 sal_uInt16 i; 2122 bool bWriteCP = true; 2123 2124 switch ( nTTyp ) 2125 { 2126 case TXT_ATN: 2127 { 2128 // then write first the GrpXstAtnOwners 2129 for ( i = 0; i < nLen; ++i ) 2130 { 2131 const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i]; 2132 aStrArr.push_back(rAtn.msOwner); 2133 } 2134 2135 //sort and remove duplicates 2136 ::std::sort(aStrArr.begin(), aStrArr.end()); 2137 myiter aIter = ::std::unique(aStrArr.begin(), aStrArr.end()); 2138 aStrArr.erase(aIter, aStrArr.end()); 2139 2140 if ( rWrt.bWrtWW8 ) 2141 { 2142 for ( i = 0; i < aStrArr.size(); ++i ) 2143 { 2144 const String& rStr = aStrArr[i]; 2145 SwWW8Writer::WriteShort(*rWrt.pTableStrm, rStr.Len()); 2146 SwWW8Writer::WriteString16(*rWrt.pTableStrm, rStr, 2147 false); 2148 } 2149 } 2150 else 2151 { 2152 for ( i = 0; i < aStrArr.size(); ++i ) 2153 { 2154 const String& rStr = aStrArr[i]; 2155 *rWrt.pTableStrm << (sal_uInt8)rStr.Len(); 2156 SwWW8Writer::WriteString8(*rWrt.pTableStrm, rStr, false, 2157 RTL_TEXTENCODING_MS_1252); 2158 } 2159 } 2160 2161 rFib.fcGrpStAtnOwners = nFcStart; 2162 nFcStart = rWrt.pTableStrm->Tell(); 2163 rFib.lcbGrpStAtnOwners = nFcStart - rFib.fcGrpStAtnOwners; 2164 2165 // Write the extended >= Word XP ATLD records 2166 if( rWrt.bWrtWW8 ) 2167 { 2168 for( i = 0; i < nLen; ++i ) 2169 { 2170 const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i]; 2171 2172 sal_uInt32 nDTTM = sw::ms::DateTime2DTTM(rAtn.maDateTime); 2173 2174 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nDTTM ); 2175 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 ); 2176 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); 2177 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); 2178 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); 2179 } 2180 2181 rFib.fcAtrdExtra = nFcStart; 2182 nFcStart = rWrt.pTableStrm->Tell(); 2183 rFib.lcbAtrdExtra = nFcStart - rFib.fcAtrdExtra; 2184 rFib.fcHplxsdr = 0x01010002; //WTF, but apparently necessary 2185 rFib.lcbHplxsdr = 0; 2186 } 2187 } 2188 break; 2189 case TXT_TXTBOX: 2190 case TXT_HFTXTBOX: 2191 { 2192 pTxtPos->Write( *rWrt.pTableStrm ); 2193 const SvULongs* pShapeIds = GetShapeIdArr(); 2194 ASSERT( pShapeIds, "wo sind die ShapeIds?" ); 2195 2196 // nLen = pTxtPos->Count(); 2197 for ( i = 0; i < nLen; ++i ) 2198 { 2199 // write textbox story - FTXBXS 2200 // is it an writer or sdr - textbox? 2201 const SdrObject* pObj = (SdrObject*)aCntnt[ i ]; 2202 sal_Int32 nCnt = 1; 2203 if (pObj && !pObj->ISA( SdrTextObj ) ) 2204 { 2205 // find the "highest" SdrObject of this 2206 const SwFrmFmt& rFmt = *::FindFrmFmt( pObj ); 2207 2208 const SwFmtChain* pChn = &rFmt.GetChain(); 2209 while ( pChn->GetNext() ) 2210 { 2211 // has a chain? 2212 // then calc the cur pos in the chain 2213 ++nCnt; 2214 pChn = &pChn->GetNext()->GetChain(); 2215 } 2216 } 2217 if( NULL == pObj ) 2218 { 2219 if( i < aSpareFmts.Count() && aSpareFmts[ i ] ) 2220 { 2221 const SwFrmFmt& rFmt = *(const SwFrmFmt*)aSpareFmts[ i ]; 2222 2223 const SwFmtChain* pChn = &rFmt.GetChain(); 2224 while( pChn->GetNext() ) 2225 { 2226 // has a chain? 2227 // then calc the cur pos in the chain 2228 ++nCnt; 2229 pChn = &pChn->GetNext()->GetChain(); 2230 } 2231 } 2232 } 2233 // long cTxbx / iNextReuse 2234 SwWW8Writer::WriteLong( *rWrt.pTableStrm, nCnt ); 2235 // long cReusable 2236 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); 2237 // short fReusable 2238 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 ); 2239 // long reserved 2240 SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 ); 2241 // long lid 2242 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 2243 (*pShapeIds)[i]); 2244 // long txidUndo 2245 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); 2246 } 2247 SwWW8Writer::FillCount( *rWrt.pTableStrm, 22 ); 2248 bWriteCP = false; 2249 } 2250 break; 2251 } 2252 2253 if ( bWriteCP ) 2254 { 2255 // Schreibe CP-Positionen 2256 for ( i = 0; i < nLen; i++ ) 2257 SwWW8Writer::WriteLong( *rWrt.pTableStrm, aCps[ i ] ); 2258 2259 // n+1-te CP-Pos nach Handbuch 2260 SwWW8Writer::WriteLong( *rWrt.pTableStrm, 2261 rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpEdn + 2262 rFib.ccpTxbx + rFib.ccpHdrTxbx + 1 ); 2263 2264 if ( TXT_ATN == nTTyp ) 2265 { 2266 for ( i = 0; i < nLen; ++i ) 2267 { 2268 const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i]; 2269 2270 //aStrArr is sorted 2271 myiter aIter = ::std::lower_bound(aStrArr.begin(), 2272 aStrArr.end(), rAtn.msOwner); 2273 ASSERT(aIter != aStrArr.end() && *aIter == rAtn.msOwner, 2274 "Impossible"); 2275 sal_uInt16 nFndPos = static_cast< sal_uInt16 >(aIter - aStrArr.begin()); 2276 String sAuthor(*aIter); 2277 sal_uInt8 nNameLen = (sal_uInt8)sAuthor.Len(); 2278 if ( nNameLen > 9 ) 2279 { 2280 sAuthor.Erase( 9 ); 2281 nNameLen = 9; 2282 } 2283 2284 // xstUsrInitl[ 10 ] pascal-style String holding initials 2285 // of annotation author 2286 if ( rWrt.bWrtWW8 ) 2287 { 2288 SwWW8Writer::WriteShort(*rWrt.pTableStrm, nNameLen); 2289 SwWW8Writer::WriteString16(*rWrt.pTableStrm, sAuthor, 2290 false); 2291 SwWW8Writer::FillCount( *rWrt.pTableStrm, 2292 (9 - nNameLen) * 2 ); 2293 2294 } 2295 else 2296 { 2297 *rWrt.pTableStrm << nNameLen; 2298 SwWW8Writer::WriteString8(*rWrt.pTableStrm, sAuthor, 2299 false, RTL_TEXTENCODING_MS_1252); 2300 SwWW8Writer::FillCount(*rWrt.pTableStrm, 9 - nNameLen); 2301 } 2302 2303 //SVBT16 ibst; // index into GrpXstAtnOwners 2304 //SVBT16 ak; // not used 2305 //SVBT16 grfbmc; // not used 2306 //SVBT32 ITagBkmk; // when not -1, this tag identifies the 2307 2308 SwWW8Writer::WriteShort( *rWrt.pTableStrm, nFndPos ); 2309 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 ); 2310 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 ); 2311 SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 ); 2312 } 2313 } 2314 else 2315 { 2316 sal_uInt16 nNo = 0; 2317 for ( i = 0; i < nLen; ++i ) // Schreibe Flags 2318 { 2319 const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ]; 2320 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 2321 pFtn->GetNumStr().Len() ? 0 : ++nNo ); 2322 } 2323 } 2324 } 2325 rRefStart = nFcStart; 2326 nFcStart = rWrt.pTableStrm->Tell(); 2327 rRefCount = nFcStart - rRefStart; 2328 2329 pTxtPos->Write( *rWrt.pTableStrm ); 2330 2331 switch ( nTTyp ) 2332 { 2333 case TXT_TXTBOX: 2334 case TXT_HFTXTBOX: 2335 for ( i = 0; i < nLen; ++i ) 2336 { 2337 // write break descriptor (BKD) 2338 // short itxbxs 2339 SwWW8Writer::WriteShort( *rWrt.pTableStrm, i ); 2340 // short dcpDepend 2341 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 ); 2342 // short flags : icol/fTableBreak/fColumnBreak/fMarked/ 2343 // fUnk/fTextOverflow 2344 SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0x800 ); 2345 } 2346 SwWW8Writer::FillCount( *rWrt.pTableStrm, 6 ); 2347 break; 2348 } 2349 2350 rTxtStart = nFcStart; 2351 rTxtCount = rWrt.pTableStrm->Tell() - nFcStart; 2352 } 2353 2354 const SvULongs* WW8_WrPlcSubDoc::GetShapeIdArr() const 2355 { 2356 return 0; 2357 } 2358 2359 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 2360