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