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