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