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