xref: /aoo4110/main/sw/source/filter/ww8/ww8atr.cxx (revision b1cdbd2c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
27 
28 /*
29  * This file contains methods for the WW8 output
30  * (nodes, attributes, formats und chars).
31  */
32 
33 #include <hintids.hxx>
34 
35 #include <vcl/svapp.hxx>
36 #include <vcl/salbtype.hxx>
37 #include <svl/zformat.hxx>
38 #include <svl/itemiter.hxx>
39 #include <svl/whiter.hxx>
40 #include <editeng/fontitem.hxx>
41 #include <editeng/tstpitem.hxx>
42 #include <editeng/adjitem.hxx>
43 #include <editeng/spltitem.hxx>
44 #include <editeng/widwitem.hxx>
45 #include <editeng/lspcitem.hxx>
46 #include <editeng/keepitem.hxx>
47 #include <editeng/shaditem.hxx>
48 #include <editeng/brshitem.hxx>
49 #include <editeng/postitem.hxx>
50 #include <editeng/wghtitem.hxx>
51 #include <editeng/kernitem.hxx>
52 #include <editeng/crsditem.hxx>
53 #include <editeng/cmapitem.hxx>
54 #include <editeng/wrlmitem.hxx>
55 #include <editeng/udlnitem.hxx>
56 #include <editeng/langitem.hxx>
57 #include <editeng/escpitem.hxx>
58 #include <editeng/fhgtitem.hxx>
59 #include <editeng/colritem.hxx>
60 #include <editeng/hyznitem.hxx>
61 #include <editeng/brkitem.hxx>
62 #include <editeng/lrspitem.hxx>
63 #include <editeng/ulspitem.hxx>
64 #include <editeng/boxitem.hxx>
65 #include <editeng/cntritem.hxx>
66 #include <editeng/shdditem.hxx>
67 #include <editeng/akrnitem.hxx>
68 #include <editeng/pbinitem.hxx>
69 #include <editeng/emphitem.hxx>
70 #include <editeng/twolinesitem.hxx>
71 #include <editeng/charscaleitem.hxx>
72 #include <editeng/charrotateitem.hxx>
73 #include <editeng/charreliefitem.hxx>
74 #include <editeng/paravertalignitem.hxx>
75 #include <editeng/pgrditem.hxx>
76 #include <editeng/frmdiritem.hxx>
77 #include <editeng/blnkitem.hxx>
78 #include <editeng/charhiddenitem.hxx>
79 #include <editeng/paperinf.hxx>
80 #include <fmtfld.hxx>
81 #include <fchrfmt.hxx>
82 #include <fmtfsize.hxx>
83 #include <fmtpdsc.hxx>
84 #include <fmtornt.hxx>
85 #include <fmtanchr.hxx>
86 #include <fmtclds.hxx>
87 #include <fmtsrnd.hxx>
88 #include <fmtftn.hxx>
89 #include <fmtflcnt.hxx>
90 #include <frmatr.hxx>
91 #include <swtable.hxx>
92 #include <fmtinfmt.hxx>
93 #include <txtfld.hxx>
94 #include <txtftn.hxx>
95 #include <poolfmt.hxx>
96 #include <doc.hxx>          // Doc for footnotes
97 #include <pam.hxx>
98 #include <paratr.hxx>
99 #include <fldbas.hxx>       // for SwField
100 #include <docufld.hxx>      // for SwField
101 #include <expfld.hxx>
102 #include <pagedesc.hxx>     // for SwPageDesc
103 #include <flddat.hxx>       // for Date fields
104 #include <ndtxt.hxx>        // for Numrules
105 #include <swrect.hxx>
106 #include <reffld.hxx>
107 #include <ftninfo.hxx>
108 #include <charfmt.hxx>
109 #include <section.hxx>
110 #include <lineinfo.hxx>
111 #include <fmtline.hxx>
112 #include <tox.hxx>
113 #include <fmtftntx.hxx>
114 #include <breakit.hxx>
115 #include <com/sun/star/i18n/ScriptType.hdl>
116 #include <unotools/localedatawrapper.hxx>
117 #include <tgrditem.hxx>
118 #include <flddropdown.hxx>
119 #include <chpfld.hxx>
120 #include <fmthdft.hxx>
121 
122 #include <writerfilter/doctok/sprmids.hxx>
123 
124 #include <fmtcntnt.hxx>
125 #include "writerhelper.hxx"
126 #include "writerwordglue.hxx"
127 #include "wrtww8.hxx"
128 #include "ww8par.hxx"
129 #include "ww8attributeoutput.hxx"
130 #include "fields.hxx"
131 #include <vcl/outdev.hxx>
132 #include <i18npool/mslangid.hxx>
133 
134 using namespace ::com::sun::star;
135 using namespace nsFieldFlags;
136 using namespace nsSwDocInfoSubType;
137 
138 /*
139  * um nicht immer wieder nach einem Update festzustellen, das irgendwelche
140  * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle
141  * definiert und mit der akt. verglichen. Bei unterschieden wird der
142  * Compiler schon meckern.
143  *
144  * diese Section und die dazugeherigen Tabellen muessen in folgenden Files
145  * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx
146 */
147 
148 #if !defined(MSC) && !defined(UNX) && !defined(PPC) && !defined(CSET) && !defined(__MWERKS__) && !defined(WTC) && !defined(__MINGW32__) && !defined(OS2)
149 
150 #define ATTRFNTAB_SIZE 130
151 #if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN
152 #   error "Attribut-Tabelle ist ungueltigt. Wurden neue Hint-ID's zugefuegt ??"
153 #endif
154 
155 #define NODETAB_SIZE 3
156 #if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN
157 #   error "Node-Tabelle ist ungueltigt. Wurden neue Hint-ID's zugefuegt ??"
158 #endif
159 
160 #endif
161 
162 using namespace sw::util;
163 using namespace sw::types;
164 
CollapseScriptsforWordOk(sal_uInt16 nScript,sal_uInt16 nWhich)165 bool WW8Export::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
166 {
167     bool bRet = true;
168     if ( nScript == i18n::ScriptType::ASIAN )
169     {
170         //for asian in ww8, there is only one fontsize
171         //and one fontstyle (posture/weight) for ww6
172         //there is the additional problem that there
173         //is only one font setting for all three scripts
174         switch ( nWhich )
175         {
176             case RES_CHRATR_FONTSIZE:
177             case RES_CHRATR_POSTURE:
178             case RES_CHRATR_WEIGHT:
179                 bRet = false;
180                 break;
181             case RES_CHRATR_LANGUAGE:
182             case RES_CHRATR_CTL_FONT:
183             case RES_CHRATR_CTL_FONTSIZE:
184             case RES_CHRATR_CTL_LANGUAGE:
185             case RES_CHRATR_CTL_POSTURE:
186             case RES_CHRATR_CTL_WEIGHT:
187                 if (bWrtWW8 == 0)
188                     bRet = false;
189             default:
190                 break;
191         }
192     }
193     else if ( nScript == i18n::ScriptType::COMPLEX )
194     {
195         //Complex is ok in ww8, but for ww6 there is only
196         //one font, one fontsize, one fontsize (weight/posture)
197         //and only one language
198         if ( bWrtWW8 == 0 )
199         {
200             switch ( nWhich )
201             {
202                 case RES_CHRATR_CJK_FONT:
203                 case RES_CHRATR_CJK_FONTSIZE:
204                 case RES_CHRATR_CJK_POSTURE:
205                 case RES_CHRATR_CJK_WEIGHT:
206                 case RES_CHRATR_CJK_LANGUAGE:
207                 case RES_CHRATR_FONT:
208                 case RES_CHRATR_FONTSIZE:
209                 case RES_CHRATR_POSTURE:
210                 case RES_CHRATR_WEIGHT:
211                 case RES_CHRATR_LANGUAGE:
212                     bRet = false;
213                     break;
214                 default:
215                     break;
216             }
217         }
218     }
219     else
220     {
221         //for western in ww8, there is only one fontsize
222         //and one fontstyle (posture/weight) for ww6
223         //there is the additional problem that there
224         //is only one font setting for all three scripts
225         switch ( nWhich )
226         {
227             case RES_CHRATR_CJK_FONTSIZE:
228             case RES_CHRATR_CJK_POSTURE:
229             case RES_CHRATR_CJK_WEIGHT:
230                 bRet = false;
231                 break;
232             case RES_CHRATR_CJK_LANGUAGE:
233             case RES_CHRATR_CTL_FONT:
234             case RES_CHRATR_CTL_FONTSIZE:
235             case RES_CHRATR_CTL_LANGUAGE:
236             case RES_CHRATR_CTL_POSTURE:
237             case RES_CHRATR_CTL_WEIGHT:
238                 if ( bWrtWW8 == 0 )
239                     bRet = false;
240             default:
241                 break;
242         }
243     }
244     return bRet;
245 }
246 
247 //------------------------------------------------------------
248 //  Hilfsroutinen fuer Styles
249 //------------------------------------------------------------
250 
ExportPoolItemsToCHP(sw::PoolItems & rItems,sal_uInt16 nScript)251 void MSWordExportBase::ExportPoolItemsToCHP( sw::PoolItems &rItems, sal_uInt16 nScript )
252 {
253     sw::cPoolItemIter aEnd = rItems.end();
254     for ( sw::cPoolItemIter aI = rItems.begin(); aI != aEnd; ++aI )
255     {
256         const SfxPoolItem *pItem = aI->second;
257         sal_uInt16 nWhich = pItem->Which();
258         if ( ( isCHRATR( nWhich ) || isTXTATR( nWhich ) ) && CollapseScriptsforWordOk( nScript, nWhich ) )
259         {
260 			 //In the id definition, RES_TXTATR_INETFMT must precede RES_TXTATR_CHARFMT, so that link style can overwrite char style.
261 			 //and in #i24291# it describes "All we want to do is ensure for now is that if a charfmt exist in the character
262 			 //properties that it rises to the top and is exported first."
263 		     //In bug 119649, it is in such situation, so we need to ignore the link style when doing ms word filter exports and
264 			 //add the second judgement for #i24291# definition.
265 			 if ( nWhich == RES_TXTATR_INETFMT && ( rItems.begin()->second->Which() == RES_TXTATR_CHARFMT ) )
266 				 continue;
267             AttrOutput().OutputItem( *pItem );
268         }
269     }
270 }
271 
272 /*
273  * Format wie folgt ausgeben:
274  *      - gebe die Attribute aus; ohne Parents!
275  */
276 
OutputItemSet(const SfxItemSet & rSet,bool bPapFmt,bool bChpFmt,sal_uInt16 nScript,bool bExportParentItemSet)277 void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFmt, bool bChpFmt, sal_uInt16 nScript,
278                                       bool bExportParentItemSet )
279 {
280     if( bExportParentItemSet || rSet.Count() )
281     {
282         const SfxPoolItem* pItem;
283         pISet = &rSet;                  // fuer Doppel-Attribute
284 
285         // If frame dir is set, but not adjust, then force adjust as well
286         if ( bPapFmt && SFX_ITEM_SET == rSet.GetItemState( RES_FRAMEDIR, bExportParentItemSet ) )
287         {
288             // No explicit adjust set ?
289             if ( SFX_ITEM_SET != rSet.GetItemState( RES_PARATR_ADJUST, bExportParentItemSet ) )
290             {
291                 if ( 0 != ( pItem = rSet.GetItem( RES_PARATR_ADJUST, bExportParentItemSet ) ) )
292                 {
293                     // then set the adjust used by the parent format
294                     AttrOutput().OutputItem( *pItem );
295                 }
296             }
297         }
298 
299         if ( bPapFmt && SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_NUMRULE, bExportParentItemSet, &pItem ) )
300         {
301             AttrOutput().OutputItem( *pItem );
302 
303             // switch off the numerbering?
304             if ( !( (SwNumRuleItem*)pItem )->GetValue().Len() &&
305                  SFX_ITEM_SET != rSet.GetItemState( RES_LR_SPACE, false) &&
306                  SFX_ITEM_SET == rSet.GetItemState( RES_LR_SPACE, true, &pItem ) )
307             {
308                 // the set the LR-Space of the parentformat!
309                 AttrOutput().OutputItem( *pItem );
310             }
311         }
312 
313         sw::PoolItems aItems;
314         GetPoolItems( rSet, aItems, bExportParentItemSet );
315         if ( bChpFmt )
316             ExportPoolItemsToCHP(aItems, nScript);
317 
318         if ( bPapFmt )
319         {
320             sw::cPoolItemIter aEnd = aItems.end();
321             for ( sw::cPoolItemIter aI = aItems.begin(); aI != aEnd; ++aI )
322             {
323                 pItem = aI->second;
324                 sal_uInt16 nWhich = pItem->Which();
325                 if ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END && nWhich != RES_PARATR_NUMRULE)
326                     AttrOutput().OutputItem( *pItem );
327             }
328         }
329         pISet = 0;                      // fuer Doppel-Attribute
330     }
331 }
332 #include "switerator.hxx"
GatherChapterFields()333 void MSWordExportBase::GatherChapterFields()
334 {
335     //If the header/footer contains a chapter field
336 	SwFieldType* pType = pDoc->GetSysFldType( RES_CHAPTERFLD );
337     SwIterator<SwFmtFld,SwFieldType> aFmtFlds( *pType );
338     for ( SwFmtFld* pFld = aFmtFlds.First(); pFld; pFld = aFmtFlds.Next() )
339     {
340         if (const SwTxtFld *pTxtFld = pFld->GetTxtFld())
341         {
342             const SwTxtNode &rTxtNode = pTxtFld->GetTxtNode();
343             maChapterFieldLocs.push_back(rTxtNode.GetIndex());
344         }
345     }
346 }
347 
CntntContainsChapterField(const SwFmtCntnt & rCntnt) const348 bool MSWordExportBase::CntntContainsChapterField(const SwFmtCntnt &rCntnt) const
349 {
350     bool bRet = false;
351     if ( const SwNodeIndex* pSttIdx = rCntnt.GetCntntIdx() )
352     {
353         SwNodeIndex aIdx( *pSttIdx, 1 );
354         SwNodeIndex aEnd( *pSttIdx->GetNode().EndOfSectionNode() );
355         sal_uLong nStart = aIdx.GetIndex();
356         sal_uLong nEnd = aEnd.GetIndex();
357         //If the header/footer contains a chapter field
358         mycCFIter aIEnd = maChapterFieldLocs.end();
359         for ( mycCFIter aI = maChapterFieldLocs.begin(); aI != aIEnd; ++aI )
360         {
361             if ( ( nStart <= *aI ) && ( *aI <= nEnd ) )
362             {
363                 bRet = true;
364                 break;
365             }
366         }
367     }
368     return bRet;
369 }
370 
FmtHdFtContainsChapterField(const SwFrmFmt & rFmt) const371 bool MSWordExportBase::FmtHdFtContainsChapterField(const SwFrmFmt &rFmt) const
372 {
373     if ( maChapterFieldLocs.empty() )
374         return false;
375 
376     const SwFrmFmt *pFmt = 0;
377 
378     pFmt = rFmt.GetHeader().GetHeaderFmt();
379     if ( pFmt && CntntContainsChapterField( pFmt->GetCntnt() ) )
380         return true;
381 
382     pFmt = rFmt.GetFooter().GetFooterFmt();
383     if ( pFmt && CntntContainsChapterField( pFmt->GetCntnt() ) )
384         return true;
385 
386     return false;
387 }
388 
SetAktPageDescFromNode(const SwNode & rNd)389 bool MSWordExportBase::SetAktPageDescFromNode(const SwNode &rNd)
390 {
391     bool bNewPageDesc = false;
392     const SwPageDesc* pCurrent = SwPageDesc::GetPageDescOfNode(rNd);
393     ASSERT(pCurrent && pAktPageDesc, "Not possible surely");
394     if (pAktPageDesc && pCurrent)
395     {
396         if (pCurrent != pAktPageDesc)
397         {
398             if (pAktPageDesc->GetFollow() != pCurrent)
399                 bNewPageDesc = true;
400             else
401             {
402                 const SwFrmFmt& rTitleFmt = pAktPageDesc->GetMaster();
403                 const SwFrmFmt& rFollowFmt = pCurrent->GetMaster();
404 
405                 bNewPageDesc = !IsPlausableSingleWordSection(rTitleFmt,
406                     rFollowFmt);
407             }
408             pAktPageDesc = pCurrent;
409         }
410         else
411         {
412             const SwFrmFmt &rFmt = pCurrent->GetMaster();
413             bNewPageDesc = FmtHdFtContainsChapterField(rFmt);
414         }
415     }
416     return bNewPageDesc;
417 }
418 
419 // Da WW nur Break-After ( Pagebreak und Sectionbreaks ) kennt, im SW aber
420 // Bagebreaks "vor" und "nach" und Pagedescs nur "vor" existieren, werden
421 // die Breaks 2* durchgeklimpert, naemlich vor und hinter jeder Zeile.
422 // Je nach BreakTyp werden sie vor oder nach der Zeile gesetzt.
423 // Es duerfen nur Funktionen gerufen werden, die nicht in den
424 // Ausgabebereich pO schreiben, da dieser nur einmal fuer CHP und PAP existiert
425 // und damit im falschen landen wuerden.
OutputSectionBreaks(const SfxItemSet * pSet,const SwNode & rNd)426 void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode& rNd )
427 {
428     if ( bStyDef || bOutKF || bInWriteEscher || bOutPageDescs )
429         return;
430 
431     bBreakBefore = true;
432 
433     bool bNewPageDesc = false;
434     const SfxPoolItem* pItem=0;
435     const SwFmtPageDesc *pPgDesc=0;
436 
437     //Output a sectionbreak if theres a new pagedesciptor.  otherwise output a
438     //pagebreak if there is a pagebreak here, unless the new page (follow
439     //style) is different to the current one, in which case plump for a
440     //section.
441     bool bBreakSet = false;
442 
443     const SwPageDesc * pPageDesc = rNd.FindPageDesc(sal_False);
444 
445     if ((!Sections().HeaderFooterWritten()) && (pAktPageDesc != pPageDesc))
446     {
447         bBreakSet = true;
448         bNewPageDesc = true;
449         pAktPageDesc = pPageDesc;
450     }
451 
452     if ( pSet && pSet->Count() )
453     {
454         if ( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem ) &&
455              dynamic_cast<const SwFmtPageDesc*>(pItem)->GetRegisteredIn() != NULL)
456         {
457             bBreakSet = true;
458             bNewPageDesc = true;
459             pPgDesc = (const SwFmtPageDesc*)pItem;
460             pAktPageDesc = pPgDesc->GetPageDesc();
461         }
462         else if ( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, false, &pItem ) )
463         {
464             // --> FME 2007-05-30 #146867# Word does not like hard break attributes in some table cells
465             bool bRemoveHardBreakInsideTable = false;
466             if ( bOutTable )
467             {
468                 const SwTableNode* pTableNode = rNd.FindTableNode();
469                 if ( pTableNode )
470                 {
471                     const SwTableBox* pBox = rNd.GetTblBox();
472                     const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0;
473                     // but only for non-complex tables
474                     if ( pLine && !pLine->GetUpper() )
475                     {
476                         // check if box is not first in that line:
477                         if ( 0 < pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() )
478                         {
479                             bRemoveHardBreakInsideTable = true;
480                         }
481                     }
482                 }
483             }
484             // <--
485 
486             bBreakSet = true;
487 
488             if ( !bRemoveHardBreakInsideTable )
489             {
490                 ASSERT(pAktPageDesc, "should not be possible");
491                 /*
492                  If because of this pagebreak the page desc following the page
493                  break is the follow style of the current page desc then output a
494                  section break using that style instead.  At least in those cases
495                  we end up with the same style in word and writer, nothing can be
496                  done when it happens when we get a new pagedesc because we
497                  overflow from the first page style.
498                 */
499                 if ( pAktPageDesc )
500                 {
501                     // --> OD 2007-05-30 #i76301#
502                     // assure that there is a page break before set at the node.
503                     const SvxFmtBreakItem* pBreak = dynamic_cast<const SvxFmtBreakItem*>(pItem);
504                     if ( pBreak &&
505                          pBreak->GetBreak() == SVX_BREAK_PAGE_BEFORE )
506                     {
507                         bNewPageDesc = SetAktPageDescFromNode( rNd );
508                     }
509                     // <--
510                 }
511                 if ( !bNewPageDesc )
512                     AttrOutput().OutputItem( *pItem );
513             }
514         }
515     }
516 
517     /*
518     #i9301#
519     No explicit page break, lets see if the style had one and we've moved to a
520     new page style because of it, if we have to then we take the opportunity to
521     set the equivalent word section here. We *could* do it for every paragraph
522     that moves onto a new page because of layout, but that would be insane.
523     */
524     bool bHackInBreak = false;
525     if ( !bBreakSet )
526     {
527         if ( const SwCntntNode *pNd = rNd.GetCntntNode() )
528         {
529             const SvxFmtBreakItem &rBreak =
530                 ItemGet<SvxFmtBreakItem>( *pNd, RES_BREAK );
531             if ( rBreak.GetBreak() == SVX_BREAK_PAGE_BEFORE )
532                 bHackInBreak = true;
533             else
534             {   // Even a pagedesc item is set, the break item can be set 'NONE',
535                 // but a pagedesc item is an implicit page break before...
536                 const SwFmtPageDesc &rPageDesc =
537                     ItemGet<SwFmtPageDesc>( *pNd, RES_PAGEDESC );
538                 if ( rPageDesc.KnowsPageDesc() )
539                     bHackInBreak = true;
540             }
541         }
542     }
543 
544     if ( bHackInBreak )
545     {
546         ASSERT( pAktPageDesc, "should not be possible" );
547         if ( pAktPageDesc )
548             bNewPageDesc = SetAktPageDescFromNode( rNd );
549     }
550 
551     if ( bNewPageDesc && pAktPageDesc )
552     {
553         PrepareNewPageDesc( pSet, rNd, pPgDesc, pAktPageDesc );
554     }
555     bBreakBefore = false;
556 }
557 
558 // --> OD 2007-05-29 #i76300#
OutputFollowPageDesc(const SfxItemSet * pSet,const SwTxtNode * pNd)559 bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTxtNode* pNd )
560 {
561     bool bRet = false;
562 
563     if ( pNd &&
564          pAktPageDesc &&
565          pAktPageDesc != pAktPageDesc->GetFollow() )
566     {
567         PrepareNewPageDesc( pSet, *pNd, 0, pAktPageDesc->GetFollow() );
568         bRet = true;
569     }
570 
571     return bRet;
572 }
573 
GetSectionFormat(const SwNode & rNd) const574 const SwSectionFmt* MSWordExportBase::GetSectionFormat( const SwNode& rNd ) const
575 {
576     const SwSectionFmt* pFmt = NULL;
577     const SwSectionNode* pSect = rNd.FindSectionNode();
578     if ( pSect &&
579          CONTENT_SECTION == pSect->GetSection().GetType() )
580     {
581         pFmt = pSect->GetSection().GetFmt();
582     }
583 
584     return pFmt;
585 }
586 
GetSectionLineNo(const SfxItemSet * pSet,const SwNode & rNd) const587 sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNode& rNd ) const
588 {
589     const SwFmtLineNumber* pNItem = 0;
590     if ( pSet )
591     {
592         pNItem = &( ItemGet<SwFmtLineNumber>( *pSet, RES_LINENUMBER ) );
593     }
594     else if ( const SwCntntNode *pNd = rNd.GetCntntNode() )
595     {
596         pNItem = &( ItemGet<SwFmtLineNumber>( *pNd, RES_LINENUMBER ) );
597     }
598 
599     return pNItem? pNItem->GetStartValue() : 0;
600 }
601 
PrepareNewPageDesc(const SfxItemSet * pSet,const SwNode & rNd,const SwFmtPageDesc * pNewPgDescFmt,const SwPageDesc * pNewPgDesc)602 void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet,
603                                       const SwNode& rNd,
604                                       const SwFmtPageDesc* pNewPgDescFmt,
605                                       const SwPageDesc* pNewPgDesc )
606 {
607     // Die PageDescs werden beim Auftreten von PageDesc-Attributen nur in
608     // WW8Writer::pSepx mit der entsprechenden Position eingetragen.  Das
609     // Aufbauen und die Ausgabe der am PageDesc haengenden Attribute und
610     // Kopf/Fusszeilen passiert nach dem Haupttext und seinen Attributen.
611 
612     sal_uLong nFcPos = ReplaceCr( msword::PageBreak ); // Page/Section-Break
613 
614     // tatsaechlich wird hier NOCH NICHTS ausgegeben, sondern
615     // nur die Merk-Arrays aCps, aSects entsprechend ergaenzt
616     if ( !nFcPos )
617         return;
618 
619     const SwSectionFmt* pFmt = GetSectionFormat( rNd );
620     const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
621 
622     ASSERT( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
623 
624     if ( pNewPgDescFmt )
625     {
626         pSepx->AppendSep( Fc2Cp( nFcPos ), *pNewPgDescFmt, rNd, pFmt, nLnNm );
627     }
628     else if ( pNewPgDesc )
629     {
630         pSepx->AppendSep( Fc2Cp( nFcPos ), pNewPgDesc, rNd, pFmt, nLnNm );
631     }
632 }
633 
CorrectTabStopInSet(SfxItemSet & rSet,sal_uInt16 nAbsLeft)634 void MSWordExportBase::CorrectTabStopInSet( SfxItemSet& rSet, sal_uInt16 nAbsLeft )
635 {
636     const SvxTabStopItem *pItem =
637         sw::util::HasItem<SvxTabStopItem>( rSet, RES_PARATR_TABSTOP );
638 
639     if ( pItem )
640     {
641         // dann muss das fuer die Ausgabe korrigiert werden
642         SvxTabStopItem aTStop(*pItem);
643         for ( sal_uInt16 nCnt = 0; nCnt < aTStop.Count(); ++nCnt )
644         {
645             SvxTabStop& rTab = (SvxTabStop&)aTStop[ nCnt ];
646             if ( SVX_TAB_ADJUST_DEFAULT != rTab.GetAdjustment() &&
647                 rTab.GetTabPos() >= nAbsLeft )
648             {
649                 rTab.GetTabPos() -= nAbsLeft;
650             }
651             else
652             {
653                 aTStop.Remove( nCnt );
654                 --nCnt;
655             }
656         }
657         rSet.Put( aTStop );
658     }
659 }
660 
GetNumId(sal_uInt16 eNumType)661 sal_uInt8 WW8Export::GetNumId( sal_uInt16 eNumType )
662 {
663     sal_uInt8 nRet = 0;
664     switch( eNumType )
665     {
666     case SVX_NUM_CHARS_UPPER_LETTER:
667     case SVX_NUM_CHARS_UPPER_LETTER_N:  nRet = 3;       break;
668     case SVX_NUM_CHARS_LOWER_LETTER:
669     case SVX_NUM_CHARS_LOWER_LETTER_N:  nRet = 4;       break;
670     case SVX_NUM_ROMAN_UPPER:           nRet = 1;       break;
671     case SVX_NUM_ROMAN_LOWER:           nRet = 2;       break;
672 
673     case SVX_NUM_BITMAP:
674     case SVX_NUM_CHAR_SPECIAL:          nRet = 23;      break;
675 
676     // nix, macht WW undokumentiert auch so
677     case SVX_NUM_NUMBER_NONE:           nRet = 0xff;    break;
678     }
679     return nRet;
680 }
681 
OutlineNumbering(sal_uInt8 nLvl,const SwNumFmt & rNFmt,const SwFmt & rFmt)682 void WW8AttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt &rNFmt, const SwFmt &rFmt )
683 {
684     if ( nLvl >= WW8ListManager::nMaxLevel )
685         nLvl = WW8ListManager::nMaxLevel-1;
686 
687     if ( m_rWW8Export.bWrtWW8 )
688     {
689         // write sprmPOutLvl sprmPIlvl and sprmPIlfo
690         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_POutLvl );
691         m_rWW8Export.pO->Insert( nLvl, m_rWW8Export.pO->Count() );
692         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlvl );
693         m_rWW8Export.pO->Insert( nLvl, m_rWW8Export.pO->Count() );
694         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlfo );
695         SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
696                 1 + m_rWW8Export.GetId( *m_rWW8Export.pDoc->GetOutlineNumRule() ) );
697     }
698     else
699     {
700         m_rWW8Export.Out_SwNumLvl( nLvl );
701         // --> OD 2008-06-03 #i86652#
702 //        if (rNFmt.GetAbsLSpace())
703         if ( rNFmt.GetPositionAndSpaceMode() ==
704                                    SvxNumberFormat::LABEL_WIDTH_AND_POSITION  &&
705              rNFmt.GetAbsLSpace() )
706         // <--
707         {
708             SwNumFmt aNumFmt( rNFmt );
709             const SvxLRSpaceItem& rLR =
710                 ItemGet<SvxLRSpaceItem>( rFmt, RES_LR_SPACE );
711 
712             aNumFmt.SetAbsLSpace( writer_cast<short>(
713                     aNumFmt.GetAbsLSpace() + rLR.GetLeft() ) );
714             m_rWW8Export.Out_NumRuleAnld(
715                     *m_rWW8Export.pDoc->GetOutlineNumRule(),
716                     aNumFmt, nLvl );
717         }
718         else
719             m_rWW8Export.Out_NumRuleAnld(
720                     *m_rWW8Export.pDoc->GetOutlineNumRule(),
721                     rNFmt, nLvl );
722     }
723 }
724 
725 // --> OD 2007-06-04 #i77805#
DisallowInheritingOutlineNumbering(const SwFmt & rFmt)726 bool WW8Export::DisallowInheritingOutlineNumbering(const SwFmt &rFmt)
727 {
728     bool bRet( false );
729 
730     //If there is no numbering on this fmt, but its parent was outline
731     //numbered, then in writer this is no inheritied, but in word it would
732     //be, so we must export "no numbering" and "body level" to make word
733     //behave like writer (see #i25755)
734     if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
735     {
736         if (const SwFmt *pParent = rFmt.DerivedFrom())
737         {
738 			if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
739 			{
740 				if (bWrtWW8)
741                 {
742                     SwWW8Writer::InsUInt16(*pO, NS_sprm::LN_POutLvl);
743                     pO->Insert(sal_uInt8(9), pO->Count());
744                     SwWW8Writer::InsUInt16(*pO, NS_sprm::LN_PIlfo);
745                     SwWW8Writer::InsUInt16(*pO, 0);
746 
747                     bRet = true;
748                 }
749                 /*whats the winword 6 way to do this ?*/
750             }
751         }
752     }
753 
754     return bRet;
755 }
756 // <--
757 
OutputFormat(const SwFmt & rFmt,bool bPapFmt,bool bChpFmt,bool bFlyFmt)758 void MSWordExportBase::OutputFormat( const SwFmt& rFmt, bool bPapFmt, bool bChpFmt, bool bFlyFmt )
759 {
760     bool bCallOutSet = true;
761     const SwModify* pOldMod = pOutFmtNode;
762     pOutFmtNode = &rFmt;
763 
764     switch( rFmt.Which() )
765     {
766     case RES_CONDTXTFMTCOLL:
767     case RES_TXTFMTCOLL:
768         if( bPapFmt )
769         {
770 			if (((const SwTxtFmtColl&)rFmt).IsAssignedToListLevelOfOutlineStyle())
771 			{
772 				int nLvl = ((const SwTxtFmtColl&)rFmt).GetAssignedOutlineStyleLevel();
773 
774                 //if outline numbered
775                 // if Write StyleDefinition then write the OutlineRule
776                 const SwNumFmt& rNFmt = pDoc->GetOutlineNumRule()->Get( static_cast<sal_uInt16>( nLvl ) );
777                 if ( bStyDef )
778                     AttrOutput().OutlineNumbering( static_cast< sal_uInt8 >( nLvl ), rNFmt, rFmt );
779 
780                 // --> OD 2008-06-03 #i86652#
781 //                if (rNFmt.GetAbsLSpace())
782                 if ( rNFmt.GetPositionAndSpaceMode() ==
783                                            SvxNumberFormat::LABEL_WIDTH_AND_POSITION  &&
784                      rNFmt.GetAbsLSpace() )
785                 // <--
786                 {
787                     SfxItemSet aSet( rFmt.GetAttrSet() );
788                     SvxLRSpaceItem aLR(
789                         ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
790 
791                     aLR.SetTxtLeft( aLR.GetTxtLeft() + rNFmt.GetAbsLSpace() );
792                     aLR.SetTxtFirstLineOfst( GetWordFirstLineOffset(rNFmt));
793 
794                     aSet.Put( aLR );
795                     CorrectTabStopInSet( aSet, rNFmt.GetAbsLSpace() );
796                     OutputItemSet( aSet, bPapFmt, bChpFmt,
797                         i18n::ScriptType::LATIN, mbExportModeRTF);
798                     bCallOutSet = false;
799                 }
800             }
801             else
802             {
803                 //otherwise we might have to remove outline numbering from
804                 //what gets exported if the parent style was outline numbered
805                 // --> OD 2007-06-04 #i77805#
806                 // If inherited outline numbering is suppress, the left/right
807                 // margins has to be exported explicitly.
808                 if ( bStyDef && DisallowInheritingOutlineNumbering(rFmt) )
809                 {
810                     SfxItemSet aSet( rFmt.GetAttrSet() );
811                     SvxLRSpaceItem aLR(
812                         ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
813                     aSet.Put( aLR );
814                     OutputItemSet( aSet, bPapFmt, bChpFmt,
815                         com::sun::star::i18n::ScriptType::LATIN, mbExportModeRTF);
816                     bCallOutSet = false;
817                 }
818                 // <--
819             }
820         }
821         break;
822 
823     case RES_CHRFMT:
824         break;
825     case RES_FLYFRMFMT:
826         if (bFlyFmt)
827         {
828             ASSERT(mpParentFrame, "No parent frame, all broken");
829 
830             if (mpParentFrame)
831             {
832                 const SwFrmFmt &rFrmFmt = mpParentFrame->GetFrmFmt();
833 
834                 SfxItemSet aSet(pDoc->GetAttrPool(), RES_FRMATR_BEGIN,
835                     RES_FRMATR_END-1);
836                 aSet.Set(rFrmFmt.GetAttrSet());
837 
838                 // Fly als Zeichen werden bei uns zu Absatz-gebundenen
839                 // jetzt den Abstand vom Absatz-Rand setzen
840                 if (pFlyOffset)
841                 {
842                     aSet.Put(SwFmtHoriOrient(pFlyOffset->X()));
843                     aSet.Put(SwFmtVertOrient(pFlyOffset->Y()));
844                     SwFmtAnchor aAnchor(rFrmFmt.GetAnchor());
845                     aAnchor.SetType(eNewAnchorType);
846                     aSet.Put(aAnchor);
847                 }
848 
849                 if (SFX_ITEM_SET != aSet.GetItemState(RES_SURROUND))
850                     aSet.Put(SwFmtSurround(SURROUND_NONE));
851 
852                 bOutFlyFrmAttrs = true;
853                 //script doesn't matter if not exporting chp
854                 OutputItemSet(aSet, true, false,
855                     i18n::ScriptType::LATIN, mbExportModeRTF);
856                 bOutFlyFrmAttrs = false;
857 
858                 bCallOutSet = false;
859             }
860         }
861         break;
862     case RES_FRMFMT:
863         break;
864     default:
865         ASSERT( !this, "Which format is exported here?" );
866         break;
867     }
868 
869     if( bCallOutSet )
870         OutputItemSet( rFmt.GetAttrSet(), bPapFmt, bChpFmt,
871             i18n::ScriptType::LATIN, mbExportModeRTF);
872     pOutFmtNode = pOldMod;
873 }
874 
HasRefToObject(sal_uInt16 nTyp,const String * pName,sal_uInt16 nSeqNo)875 bool MSWordExportBase::HasRefToObject( sal_uInt16 nTyp, const String* pName, sal_uInt16 nSeqNo )
876 {
877     const SwTxtNode* pNd;
878 
879 	SwFieldType* pType = pDoc->GetSysFldType( RES_GETREFFLD );
880     SwIterator<SwFmtFld, SwFieldType> aFmtFlds( *pType );
881     for ( SwFmtFld* pFmtFld = aFmtFlds.First(); pFmtFld; pFmtFld = aFmtFlds.Next() )
882     {
883         if ( pFmtFld->GetTxtFld() && nTyp == pFmtFld->GetField()->GetSubType() &&
884              0 != ( pNd = pFmtFld->GetTxtFld()->GetpTxtNode() ) &&
885              pNd->GetNodes().IsDocNodes() )
886         {
887             const SwGetRefField& rRFld = *static_cast< SwGetRefField* >( pFmtFld->GetField() );
888             switch ( nTyp )
889             {
890                 case REF_BOOKMARK:
891                 case REF_SETREFATTR:
892                     if ( pName && *pName == rRFld.GetSetRefName() )
893                         return true;
894                     break;
895                 case REF_FOOTNOTE:
896                 case REF_ENDNOTE:
897                     if ( nSeqNo == rRFld.GetSeqNo() )
898                         return true;
899                     break;
900                 case REF_SEQUENCEFLD:
901                     break;      // ???
902                 case REF_OUTLINE:
903                     break;      // ???
904             }
905         }
906     }
907 
908     return false;
909 }
910 
GetBookmarkName(sal_uInt16 nTyp,const String * pName,sal_uInt16 nSeqNo)911 String MSWordExportBase::GetBookmarkName( sal_uInt16 nTyp, const String* pName, sal_uInt16 nSeqNo )
912 {
913     String sRet;
914     switch ( nTyp )
915     {
916         case REF_SETREFATTR:
917             if ( pName )
918             {
919                 sRet.APPEND_CONST_ASC( "Ref_" );
920                 sRet += *pName;
921             }
922             break;
923         case REF_SEQUENCEFLD:
924             break;      // ???
925         case REF_BOOKMARK:
926             if ( pName )
927                 sRet = *pName;
928             break;
929         case REF_OUTLINE:
930             break;      // ???
931         case REF_FOOTNOTE:
932             sRet.APPEND_CONST_ASC( "_RefF" );
933             sRet += String::CreateFromInt32( nSeqNo );
934             break;
935         case REF_ENDNOTE:
936             sRet.APPEND_CONST_ASC( "_RefE" );
937             sRet += String::CreateFromInt32( nSeqNo );
938             break;
939     }
940     // --> OD 2005-06-08 #i43956# - encode bookmark accordingly
941     return BookmarkToWord( sRet );
942     // <--
943 }
944 
945 //-----------------------------------------------------------------------
946 /*  */
947 /* File CHRATR.HXX: */
RTLAndCJKState(bool bIsRTL,sal_uInt16 nScript)948 void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript )
949 {
950     if ( m_rWW8Export.bWrtWW8 && bIsRTL )
951     {
952         if( m_rWW8Export.pDoc->GetDocumentType() != SwDoc::DOCTYPE_MSWORD )
953         {
954         	m_rWW8Export.InsUInt16( NS_sprm::LN_CFBiDi );
955         	m_rWW8Export.pO->Insert( (sal_uInt8)1, m_rWW8Export.pO->Count() );
956         }
957     }
958 
959     // #i46087# patch from james_clark; complex texts needs the undocumented SPRM CComplexScript with param 0x81.
960     if ( m_rWW8Export.bWrtWW8 && nScript == i18n::ScriptType::COMPLEX && !bIsRTL )
961     {
962         m_rWW8Export.InsUInt16( NS_sprm::LN_CComplexScript );
963         m_rWW8Export.pO->Insert( (sal_uInt8)0x81, m_rWW8Export.pO->Count() );
964         m_rWW8Export.pDop->bUseThaiLineBreakingRules = true;
965     }
966 }
967 
EndParagraph(ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner)968 void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
969 {
970     m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() - (mbOnTOXEnding?2:0), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
971     mbOnTOXEnding = false;
972     m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
973 
974     if ( pTextNodeInfoInner.get() != NULL )
975     {
976         if ( pTextNodeInfoInner->isEndOfLine() )
977         {
978             TableRowEnd( pTextNodeInfoInner->getDepth() );
979 
980             SVBT16 nSty;
981             ShortToSVBT16( 0, nSty );
982             m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() );     // Style #
983             TableInfoRow( pTextNodeInfoInner );
984             m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
985                     m_rWW8Export.pO->GetData() );
986             m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
987 	    //For Bug 119650, should break the properties of CHP PLC after a paragraph end.
988 	    m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
989 		    m_rWW8Export.pO->GetData() );
990         }
991     }
992 }
993 
StartRunProperties()994 void WW8AttributeOutput::StartRunProperties()
995 {
996     WW8_WrPlcFld* pCurrentFields = m_rWW8Export.CurrentFieldPlc();
997     m_nFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;
998 }
999 
1000 
StartRun(const SwRedlineData * pRedlineData)1001 void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData )
1002 {
1003     if (pRedlineData)
1004     {
1005         const String &rComment = pRedlineData->GetComment();
1006         //Only possible to export to main text
1007         if (rComment.Len() && (m_rWW8Export.nTxtTyp == TXT_MAINTEXT))
1008         {
1009             if (m_rWW8Export.pAtn->IsNewRedlineComment(pRedlineData))
1010             {
1011                 m_rWW8Export.pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pRedlineData );
1012                 m_rWW8Export.WritePostItBegin( m_rWW8Export.pO );
1013             }
1014         }
1015     }
1016 }
1017 
OnTOXEnding()1018 void WW8AttributeOutput::OnTOXEnding()
1019 {
1020 	mbOnTOXEnding = true;
1021 }
1022 
EndRunProperties(const SwRedlineData * pRedlineData)1023 void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
1024 {
1025     Redline( pRedlineData );
1026 
1027     WW8_WrPlcFld* pCurrentFields = m_rWW8Export.CurrentFieldPlc();
1028     sal_uInt16 nNewFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;
1029 
1030     bool bExportedFieldResult = ( m_nFieldResults != nNewFieldResults );
1031 
1032     // If we have exported a field result, then we will have been forced to
1033     // split up the text into a 0x13, 0x14, <result> 0x15 sequence with the
1034     // properties forced out at the end of the result, so the 0x15 itself
1035     // should remain clean of all other attributes to avoid #iXXXXX#
1036     if ( !bExportedFieldResult )
1037     {
1038         m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(),
1039                 m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
1040     }
1041     m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
1042 }
1043 
RunText(const String & rText,rtl_TextEncoding eCharSet)1044 void WW8AttributeOutput::RunText( const String& rText, rtl_TextEncoding eCharSet )
1045 {
1046     RawText( rText, m_rWW8Export.bWrtWW8, eCharSet );
1047 }
1048 
RawText(const String & rText,bool bForceUnicode,rtl_TextEncoding eCharSet)1049 void WW8AttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )
1050 {
1051     m_rWW8Export.OutSwString( rText, 0, rText.Len(), bForceUnicode, eCharSet );
1052 }
1053 
OutputFKP()1054 void WW8AttributeOutput::OutputFKP()
1055 {
1056     if ( m_rWW8Export.pO->Count() )
1057     {
1058         m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(),
1059                 m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
1060         m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
1061     }
1062 }
1063 
ParagraphStyle(sal_uInt16 nStyle)1064 void WW8AttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
1065 {
1066     ASSERT( !m_rWW8Export.pO->Count(), " pO ist am ZeilenEnde nicht leer" );
1067 
1068     SVBT16 nSty;
1069     ShortToSVBT16( nStyle, nSty );
1070     m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() );     // Style #
1071 }
1072 
OutputWW8Attribute(sal_uInt8 nId,bool bVal)1073 void WW8AttributeOutput::OutputWW8Attribute( sal_uInt8 nId, bool bVal )
1074 {
1075     if ( m_rWW8Export.bWrtWW8 )
1076         m_rWW8Export.InsUInt16( 8 == nId ? NS_sprm::LN_CFDStrike : NS_sprm::LN_CFBold + nId );
1077     else if (8 == nId )
1078         return; // no such attribute in WW6
1079     else
1080         m_rWW8Export.pO->Insert( 85 + nId, m_rWW8Export.pO->Count() );
1081 
1082     m_rWW8Export.pO->Insert( bVal ? 1 : 0, m_rWW8Export.pO->Count() );
1083 }
1084 
OutputWW8AttributeCTL(sal_uInt8 nId,bool bVal)1085 void WW8AttributeOutput::OutputWW8AttributeCTL( sal_uInt8 nId, bool bVal )
1086 {
1087     ASSERT( nId <= 1, "out of range" );
1088     if ( !m_rWW8Export.bWrtWW8 || nId > 1 )
1089         return;
1090 
1091     m_rWW8Export.InsUInt16( NS_sprm::LN_CFBoldBi + nId );
1092     m_rWW8Export.pO->Insert( bVal ? 1 : 0, m_rWW8Export.pO->Count() );
1093 }
1094 
CharFont(const SvxFontItem & rFont)1095 void WW8AttributeOutput::CharFont( const SvxFontItem& rFont )
1096 {
1097     sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );
1098 
1099     if ( m_rWW8Export.bWrtWW8 )
1100     {
1101         m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
1102         m_rWW8Export.InsUInt16( nFontID );
1103         m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
1104     }
1105     else
1106         m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
1107 
1108     m_rWW8Export.InsUInt16( nFontID );
1109 }
1110 
CharFontCTL(const SvxFontItem & rFont)1111 void WW8AttributeOutput::CharFontCTL( const SvxFontItem& rFont )
1112 {
1113     if ( m_rWW8Export.bWrtWW8 )
1114     {
1115         m_rWW8Export.InsUInt16( NS_sprm::LN_CFtcBi );
1116         m_rWW8Export.InsUInt16( m_rWW8Export.GetId( rFont ) );
1117     }
1118 }
1119 
CharFontCJK(const SvxFontItem & rFont)1120 void WW8AttributeOutput::CharFontCJK( const SvxFontItem& rFont )
1121 {
1122     if ( m_rWW8Export.bWrtWW8 )
1123     {
1124         m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc1 );
1125         m_rWW8Export.InsUInt16( m_rWW8Export.GetId( rFont ) );
1126     }
1127 }
1128 
CharWeightCTL(const SvxWeightItem & rWeight)1129 void WW8AttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
1130 {
1131     //Can only export in 8+, in 7- export as normal varient and expect that
1132     //upperlevel code has blocked exporting clobbering attributes
1133     if (m_rWW8Export.bWrtWW8)
1134     {
1135         OutputWW8AttributeCTL( 0, WEIGHT_BOLD == rWeight.GetWeight());
1136     }
1137     else
1138     {
1139         OutputWW8Attribute( 0, WEIGHT_BOLD == rWeight.GetWeight());
1140     }
1141 }
1142 
CharPostureCTL(const SvxPostureItem & rPosture)1143 void WW8AttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture )
1144 {
1145     // Can only export in 8+, in 7- export as normal varient and expect that
1146     // upperlevel code has blocked exporting clobbering attributes
1147     if (m_rWW8Export.bWrtWW8)
1148     {
1149         OutputWW8AttributeCTL( 1, ITALIC_NONE != rPosture.GetPosture() );
1150     }
1151     else
1152     {
1153         OutputWW8Attribute( 1, ITALIC_NONE != rPosture.GetPosture() );
1154     }
1155 }
1156 
CharPosture(const SvxPostureItem & rPosture)1157 void WW8AttributeOutput::CharPosture( const SvxPostureItem& rPosture )
1158 {
1159     OutputWW8Attribute( 1, ITALIC_NONE != rPosture.GetPosture() );
1160 }
1161 
CharWeight(const SvxWeightItem & rWeight)1162 void WW8AttributeOutput::CharWeight( const SvxWeightItem& rWeight )
1163 {
1164     OutputWW8Attribute( 0, WEIGHT_BOLD == rWeight.GetWeight() );
1165 }
1166 
1167 // Shadowed und Contour are not in WW-UI. JP: ??
CharContour(const SvxContourItem & rContour)1168 void WW8AttributeOutput::CharContour( const SvxContourItem& rContour )
1169 {
1170     OutputWW8Attribute( 3, rContour.GetValue() ? true : false);
1171 }
1172 
CharShadow(const SvxShadowedItem & rShadow)1173 void WW8AttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
1174 {
1175     OutputWW8Attribute( 4, rShadow.GetValue() ? true : false);
1176 }
1177 
CharKerning(const SvxKerningItem & rKerning)1178 void WW8AttributeOutput::CharKerning( const SvxKerningItem& rKerning )
1179 {
1180     if ( m_rWW8Export.bWrtWW8 )
1181         m_rWW8Export.InsUInt16( NS_sprm::LN_CDxaSpace );
1182     else
1183         m_rWW8Export.pO->Insert( 96, m_rWW8Export.pO->Count() );
1184 
1185     m_rWW8Export.InsUInt16( rKerning.GetValue() );
1186 }
1187 
CharAutoKern(const SvxAutoKernItem & rAutoKern)1188 void WW8AttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern )
1189 {
1190     if ( m_rWW8Export.bWrtWW8 )
1191         m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsKern );
1192     else
1193         m_rWW8Export.pO->Insert( 107, m_rWW8Export.pO->Count() );
1194 
1195     m_rWW8Export.InsUInt16( rAutoKern.GetValue() ? 1 : 0 );
1196 }
1197 
CharAnimatedText(const SvxBlinkItem & rBlink)1198 void WW8AttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
1199 {
1200     if ( m_rWW8Export.bWrtWW8 )
1201     {
1202         m_rWW8Export.InsUInt16( NS_sprm::LN_CSfxText );
1203         // At the moment the only animated text effect we support is blinking
1204         m_rWW8Export.InsUInt16( rBlink.GetValue() ? 2 : 0 );
1205     }
1206 }
1207 
CharCrossedOut(const SvxCrossedOutItem & rCrossed)1208 void WW8AttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossed )
1209 {
1210     FontStrikeout eSt = rCrossed.GetStrikeout();
1211     if ( STRIKEOUT_DOUBLE == eSt )
1212     {
1213         OutputWW8Attribute( 8, true );
1214         return;
1215     }
1216     if ( STRIKEOUT_NONE != eSt )
1217     {
1218         OutputWW8Attribute( 2, true );
1219         return;
1220     }
1221 
1222     // otherwise both off
1223     OutputWW8Attribute( 8, false );
1224     OutputWW8Attribute( 2, false );
1225 }
1226 
CharCaseMap(const SvxCaseMapItem & rCaseMap)1227 void WW8AttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
1228 {
1229     sal_uInt16 eSt = rCaseMap.GetValue();
1230     switch ( eSt )
1231     {
1232         case SVX_CASEMAP_KAPITAELCHEN:
1233             OutputWW8Attribute( 5, true );
1234             return;
1235         case SVX_CASEMAP_VERSALIEN:
1236             OutputWW8Attribute( 6, true );
1237             return;
1238         case SVX_CASEMAP_TITEL:
1239             // no such feature in word
1240             break;
1241         default:
1242             // otherwise both off
1243             OutputWW8Attribute( 5, false );
1244             OutputWW8Attribute( 6, false );
1245             return;
1246     }
1247 }
1248 
CharHidden(const SvxCharHiddenItem & rHidden)1249 void WW8AttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
1250 {
1251     OutputWW8Attribute( 7, rHidden.GetValue() );
1252 }
1253 
CharUnderline(const SvxUnderlineItem & rUnderline)1254 void WW8AttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
1255 {
1256     if ( m_rWW8Export.bWrtWW8 )
1257         m_rWW8Export.InsUInt16( NS_sprm::LN_CKul );
1258     else
1259         m_rWW8Export.pO->Insert( 94, m_rWW8Export.pO->Count() );
1260 
1261     const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_CHRATR_WORDLINEMODE );
1262     bool bWord = false;
1263     if (pItem)
1264         bWord = ((const SvxWordLineModeItem*)pItem)->GetValue() ? true : false;
1265 
1266     // WW95 - parameters:   0 = none,   1 = single, 2 = by Word,
1267     //                      3 = double, 4 = dotted, 5 = hidden
1268     // WW97 - additional parameters:
1269     //                      6 = thick,   7 = dash,       8 = dot(not used)
1270     //                      9 = dotdash 10 = dotdotdash, 11 = wave
1271     sal_uInt8 b = 0;
1272     switch ( rUnderline.GetLineStyle() )
1273     {
1274         case UNDERLINE_SINGLE:
1275             b = ( bWord ) ? 2 : 1;
1276             break;
1277         case UNDERLINE_BOLD:
1278             b = m_rWW8Export.bWrtWW8 ?  6 : 1;
1279             break;
1280         case UNDERLINE_DOUBLE:
1281             b = 3;
1282             break;
1283         case UNDERLINE_DOTTED:
1284             b = 4;
1285             break;
1286         case UNDERLINE_DASH:
1287             b = m_rWW8Export.bWrtWW8 ?  7 : 4;
1288             break;
1289         case UNDERLINE_DASHDOT:
1290             b = m_rWW8Export.bWrtWW8 ?  9 : 4;
1291             break;
1292         case UNDERLINE_DASHDOTDOT:
1293             b = m_rWW8Export.bWrtWW8 ? 10 : 4;
1294             break;
1295         case UNDERLINE_WAVE:
1296             b = m_rWW8Export.bWrtWW8 ? 11 : 3;
1297             break;
1298         // ------------  new in WW2000  -------------------------------------
1299         case UNDERLINE_BOLDDOTTED:
1300             b = m_rWW8Export.bWrtWW8 ? 20 : 4;
1301             break;
1302         case UNDERLINE_BOLDDASH:
1303             b = m_rWW8Export.bWrtWW8 ? 23 : 4;
1304             break;
1305         case UNDERLINE_LONGDASH:
1306             b = m_rWW8Export.bWrtWW8 ? 39 : 4;
1307             break;
1308         case UNDERLINE_BOLDLONGDASH:
1309             b = m_rWW8Export.bWrtWW8 ? 55 : 4;
1310             break;
1311         case UNDERLINE_BOLDDASHDOT:
1312             b = m_rWW8Export.bWrtWW8 ? 25 : 4;
1313             break;
1314         case UNDERLINE_BOLDDASHDOTDOT:
1315             b = m_rWW8Export.bWrtWW8 ? 26 : 4;
1316             break;
1317         case UNDERLINE_BOLDWAVE:
1318             b = m_rWW8Export.bWrtWW8 ? 27 : 3;
1319             break;
1320         case UNDERLINE_DOUBLEWAVE:
1321             b = m_rWW8Export.bWrtWW8 ? 43 : 3;
1322             break;
1323         case UNDERLINE_NONE:
1324             b = 0;
1325             break;
1326         default:
1327             ASSERT( rUnderline.GetLineStyle() == UNDERLINE_NONE, "Unhandled underline type" );
1328             break;
1329     }
1330 
1331     m_rWW8Export.pO->Insert( b, m_rWW8Export.pO->Count() );
1332 	Color aColor = rUnderline.GetColor();
1333 	if( aColor != COL_TRANSPARENT )
1334 	{
1335 		if( m_rWW8Export.bWrtWW8 )
1336 		{
1337 			m_rWW8Export.InsUInt16( 0x6877 );
1338 
1339 			m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( aColor.GetColor() ) );
1340 		}
1341 	}
1342 }
1343 
CharLanguage(const SvxLanguageItem & rLanguage)1344 void WW8AttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
1345 {
1346     sal_uInt16 nId = 0;
1347     if ( m_rWW8Export.bWrtWW8 )
1348     {
1349         switch ( rLanguage.Which() )
1350         {
1351             case RES_CHRATR_LANGUAGE:
1352                 nId = NS_sprm::LN_CRgLid0;
1353                 break;
1354             case RES_CHRATR_CJK_LANGUAGE:
1355                 nId = NS_sprm::LN_CRgLid1;
1356                 break;
1357             case RES_CHRATR_CTL_LANGUAGE:
1358                 nId = NS_sprm::LN_CLidBi;
1359                 break;
1360         }
1361     }
1362     else
1363         nId = 97;
1364 
1365     if ( nId )
1366     {
1367         if ( m_rWW8Export.bWrtWW8 ) // use sprmCRgLid0 rather than sprmCLid
1368             m_rWW8Export.InsUInt16( nId );
1369         else
1370             m_rWW8Export.pO->Insert( (sal_uInt8)nId, m_rWW8Export.pO->Count() );
1371         m_rWW8Export.InsUInt16( rLanguage.GetLanguage() );
1372 
1373         // unknown as to exactly why, but this seems to shadow the other
1374         // paramater in word 2000 and without it spellchecking doesn't work
1375         if ( nId == NS_sprm::LN_CRgLid0 )
1376         {
1377             m_rWW8Export.InsUInt16( 0x4873 );
1378             m_rWW8Export.InsUInt16( rLanguage.GetLanguage() );
1379         }
1380         else if ( nId == NS_sprm::LN_CLidBi )
1381         {
1382             m_rWW8Export.InsUInt16( 0x4874 );
1383             m_rWW8Export.InsUInt16( rLanguage.GetLanguage() );
1384         }
1385 
1386     }
1387 }
1388 
CharEscapement(const SvxEscapementItem & rEscapement)1389 void WW8AttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )
1390 {
1391     sal_uInt8 b = 0xFF;
1392     short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProp();
1393     if ( !nEsc )
1394     {
1395         b = 0;
1396         nEsc = 0;
1397         nProp = 100;
1398     }
1399     else if ( DFLT_ESC_PROP == nProp )
1400     {
1401         if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
1402             b = 2;
1403         else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
1404             b = 1;
1405     }
1406 
1407     if ( 0xFF != b )
1408     {
1409         if ( m_rWW8Export.bWrtWW8 )
1410             m_rWW8Export.InsUInt16( NS_sprm::LN_CIss );
1411         else
1412             m_rWW8Export.pO->Insert( 104, m_rWW8Export.pO->Count() );
1413 
1414         m_rWW8Export.pO->Insert( b, m_rWW8Export.pO->Count() );
1415     }
1416 
1417     if ( 0 == b || 0xFF == b )
1418     {
1419         long nHeight = ((SvxFontHeightItem&)m_rWW8Export.GetItem(
1420                                     RES_CHRATR_FONTSIZE )).GetHeight();
1421         if( m_rWW8Export.bWrtWW8 )
1422             m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsPos );
1423         else
1424             m_rWW8Export.pO->Insert( 101, m_rWW8Export.pO->Count() );
1425 
1426         m_rWW8Export.InsUInt16( (short)(( nHeight * nEsc + 500 ) / 1000 ));
1427 
1428         if( 100 != nProp || !b )
1429         {
1430             if( m_rWW8Export.bWrtWW8 )
1431                 m_rWW8Export.InsUInt16( NS_sprm::LN_CHps );
1432             else
1433                 m_rWW8Export.pO->Insert( 99, m_rWW8Export.pO->Count() );
1434 
1435             m_rWW8Export.InsUInt16(
1436                 msword_cast<sal_uInt16>((nHeight * nProp + 500 ) / 1000));
1437         }
1438     }
1439 }
1440 
CharFontSize(const SvxFontHeightItem & rHeight)1441 void WW8AttributeOutput::CharFontSize( const SvxFontHeightItem& rHeight )
1442 {
1443     sal_uInt16 nId = 0;
1444     if ( m_rWW8Export.bWrtWW8 )
1445     {
1446         switch ( rHeight.Which() )
1447         {
1448             case RES_CHRATR_FONTSIZE:
1449             case RES_CHRATR_CJK_FONTSIZE:
1450                 nId = NS_sprm::LN_CHps;
1451                 break;
1452             case RES_CHRATR_CTL_FONTSIZE:
1453                 nId = NS_sprm::LN_CHpsBi;
1454                 break;
1455         }
1456     }
1457     else
1458         nId = 99;
1459 
1460     if ( nId )
1461     {
1462         if ( m_rWW8Export.bWrtWW8 )
1463             m_rWW8Export.InsUInt16( nId );
1464         else
1465             m_rWW8Export.pO->Insert( (sal_uInt8)nId, m_rWW8Export.pO->Count() );
1466 
1467         m_rWW8Export.InsUInt16( (sal_uInt16)(( rHeight.GetHeight() + 5 ) / 10 ) );
1468     }
1469 }
1470 
CharScaleWidth(const SvxCharScaleWidthItem & rScaleWidth)1471 void WW8AttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
1472 {
1473     if ( m_rWW8Export.bWrtWW8 )
1474     {
1475         m_rWW8Export.InsUInt16( NS_sprm::LN_CCharScale );
1476         m_rWW8Export.InsUInt16( rScaleWidth.GetValue() );
1477     }
1478 }
1479 
CharRelief(const SvxCharReliefItem & rRelief)1480 void WW8AttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
1481 {
1482     if ( m_rWW8Export.bWrtWW8 )
1483     {
1484         sal_uInt16 nId;
1485         switch ( rRelief.GetValue() )
1486         {
1487             case RELIEF_EMBOSSED:   nId = NS_sprm::LN_CFEmboss;     break;
1488             case RELIEF_ENGRAVED:   nId = NS_sprm::LN_CFImprint;    break;
1489             default:                nId = 0;                        break;
1490         }
1491 
1492         if( nId )
1493         {
1494             m_rWW8Export.InsUInt16( nId );
1495             m_rWW8Export.pO->Insert( (sal_uInt8)0x81, m_rWW8Export.pO->Count() );
1496         }
1497         else
1498         {
1499             // switch both flags off
1500             m_rWW8Export.InsUInt16( NS_sprm::LN_CFEmboss );
1501             m_rWW8Export.pO->Insert( (sal_uInt8)0x0, m_rWW8Export.pO->Count() );
1502             m_rWW8Export.InsUInt16( NS_sprm::LN_CFImprint );
1503             m_rWW8Export.pO->Insert( (sal_uInt8)0x0, m_rWW8Export.pO->Count() );
1504         }
1505     }
1506 }
1507 
CharBidiRTL(const SfxPoolItem & rHt)1508 void WW8AttributeOutput::CharBidiRTL( const SfxPoolItem& rHt )
1509 {
1510 	const SfxInt16Item& rAttr = (const SfxInt16Item&)rHt;
1511 	if( rAttr.GetValue() == 1 )
1512 	{
1513 		m_rWW8Export.InsUInt16(0x85a);
1514 		m_rWW8Export.pO->Insert((sal_uInt8)1, m_rWW8Export.pO->Count());
1515 	}
1516 }
1517 
CharIdctHint(const SfxPoolItem & rHt)1518 void WW8AttributeOutput::CharIdctHint( const SfxPoolItem& rHt )
1519 {
1520 	const SfxInt16Item& rAttr = (const SfxInt16Item&)rHt;
1521 	m_rWW8Export.InsUInt16(0x286F);
1522 	m_rWW8Export.pO->Insert((sal_uInt8)(rAttr.GetValue()), m_rWW8Export.pO->Count());
1523 }
1524 
CharRotate(const SvxCharRotateItem & rRotate)1525 void WW8AttributeOutput::CharRotate( const SvxCharRotateItem& rRotate )
1526 {
1527     // #i28331# - check that a Value is set
1528     if ( !rRotate.GetValue() )
1529         return;
1530 
1531     if ( m_rWW8Export.bWrtWW8 && !m_rWW8Export.IsInTable() )
1532     {
1533         // #i36867 In word the text in a table is rotated via the TC or NS_sprm::LN_TTextFlow
1534         // This means you can only rotate all or none of the text adding NS_sprm::LN_CEastAsianLayout
1535         // here corrupts the table, hence !m_rWW8Export.bIsInTable
1536 
1537         m_rWW8Export.InsUInt16( NS_sprm::LN_CEastAsianLayout );
1538         m_rWW8Export.pO->Insert( (sal_uInt8)0x06, m_rWW8Export.pO->Count() ); //len 6
1539         m_rWW8Export.pO->Insert( (sal_uInt8)0x01, m_rWW8Export.pO->Count() );
1540 
1541         m_rWW8Export.InsUInt16( rRotate.IsFitToLine() ? 1 : 0 );
1542         static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 };
1543         m_rWW8Export.pO->Insert( aZeroArr, 3, m_rWW8Export.pO->Count() );
1544     }
1545 }
1546 
CharEmphasisMark(const SvxEmphasisMarkItem & rEmphasisMark)1547 void WW8AttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
1548 {
1549     if ( m_rWW8Export.bWrtWW8 )
1550     {
1551         sal_uInt8 nVal;
1552         switch ( rEmphasisMark.GetValue() )
1553         {
1554             case EMPHASISMARK_NONE:             nVal = 0;   break;
1555             case EMPHASISMARK_SIDE_DOTS:        nVal = 2;   break;
1556             case EMPHASISMARK_CIRCLE_ABOVE:     nVal = 3;   break;
1557             case EMPHASISMARK_DOTS_BELOW:       nVal = 4;   break;
1558             // case 1:
1559             default:                            nVal = 1;   break;
1560         }
1561 
1562         m_rWW8Export.InsUInt16( NS_sprm::LN_CKcd );
1563         m_rWW8Export.pO->Insert( nVal, m_rWW8Export.pO->Count() );
1564     }
1565 }
1566 
1567 // TransCol uebersetzt SW-Farben in WW. Heraus kommt die bei WW fuer
1568 // Text- und Hintergrundfarbe benutzte Codierung.
1569 // Gibt es keine direkte Entsprechung, dann wird versucht, eine moeglichst
1570 // aehnliche WW-Farbe zu finden.
1571 // return: 5-Bit-Wert ( 0..16 )
TransCol(const Color & rCol)1572 sal_uInt8 WW8Export::TransCol( const Color& rCol )
1573 {
1574     sal_uInt8 nCol = 0;      // ->Auto
1575     switch( rCol.GetColor() )
1576     {
1577     case COL_BLACK:         nCol = 1;   break;
1578     case COL_BLUE:          nCol = 9;   break;
1579     case COL_GREEN:         nCol = 11;  break;
1580     case COL_CYAN:          nCol = 10;  break;
1581     case COL_RED:           nCol = 13;  break;
1582     case COL_MAGENTA:       nCol = 12;  break;
1583     case COL_BROWN:         nCol = 14;  break;
1584     case COL_GRAY:          nCol = 15;  break;
1585     case COL_LIGHTGRAY:     nCol = 16;  break;
1586     case COL_LIGHTBLUE:     nCol = 2;   break;
1587     case COL_LIGHTGREEN:    nCol = 4;   break;
1588     case COL_LIGHTCYAN:     nCol = 3;   break;
1589     case COL_LIGHTRED:      nCol = 6;   break;
1590     case COL_LIGHTMAGENTA:  nCol = 5;   break;
1591     case COL_YELLOW:        nCol = 7;   break;
1592     case COL_WHITE:         nCol = 8;   break;
1593     case COL_AUTO:          nCol = 0;   break;
1594 
1595     default:
1596         if( !pBmpPal )
1597         {
1598             pBmpPal = new BitmapPalette( 16 );
1599             static const ColorData aColArr[ 16 ] = {
1600                 COL_BLACK,      COL_LIGHTBLUE,  COL_LIGHTCYAN,  COL_LIGHTGREEN,
1601                 COL_LIGHTMAGENTA,COL_LIGHTRED,  COL_YELLOW,     COL_WHITE,
1602                 COL_BLUE,       COL_CYAN,       COL_GREEN,      COL_MAGENTA,
1603                 COL_RED,        COL_BROWN,      COL_GRAY,       COL_LIGHTGRAY
1604             };
1605 
1606             for( sal_uInt16 i = 0; i < 16; ++i )
1607                 pBmpPal->operator[]( i ) = Color( aColArr[ i ] );
1608         }
1609         nCol = static_cast< sal_uInt8 >(pBmpPal->GetBestIndex( rCol ) + 1);
1610         break;
1611     }
1612     return nCol;
1613 }
1614 
1615 // TransBrush uebersetzt SW-Brushes in WW. Heraus kommt WW8_SHD.
1616 // Nicht-Standardfarben des SW werden noch nicht in die
1617 // Misch-Werte ( 0 .. 95% ) vom WW uebersetzt.
1618 // Return: Echte Brush ( nicht transparent )
1619 // auch bei Transparent wird z.B. fuer Tabellen eine transparente Brush
1620 // geliefert
TransBrush(const Color & rCol,WW8_SHD & rShd)1621 bool WW8Export::TransBrush(const Color& rCol, WW8_SHD& rShd)
1622 {
1623     if( rCol.GetTransparency() )
1624         rShd = WW8_SHD();               // alles Nullen : transparent
1625     else
1626     {
1627         rShd.SetFore( 0);
1628         rShd.SetBack( TransCol( rCol ) );
1629         rShd.SetStyle( bWrtWW8, 0 );
1630     }
1631     return !rCol.GetTransparency();
1632 }
1633 
SuitableBGColor(sal_uInt32 nIn)1634 sal_uInt32 SuitableBGColor(sal_uInt32 nIn)
1635 {
1636     if (nIn == COL_AUTO)
1637         return 0xFF000000;
1638     return wwUtility::RGBToBGR(nIn);
1639 }
1640 
CharColor(const SvxColorItem & rColor)1641 void WW8AttributeOutput::CharColor( const SvxColorItem& rColor )
1642 {
1643     if ( m_rWW8Export.bWrtWW8 )
1644         m_rWW8Export.InsUInt16( NS_sprm::LN_CIco );
1645     else
1646         m_rWW8Export.pO->Insert( 98, m_rWW8Export.pO->Count() );
1647 
1648     sal_uInt8 nColor = m_rWW8Export.TransCol( rColor.GetValue() );
1649     m_rWW8Export.pO->Insert( nColor, m_rWW8Export.pO->Count() );
1650 
1651     if ( m_rWW8Export.bWrtWW8 && nColor )
1652     {
1653         m_rWW8Export.InsUInt16( 0x6870 );
1654         m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( rColor.GetValue().GetColor() ) );
1655     }
1656 }
1657 
CharBackground(const SvxBrushItem & rBrush)1658 void WW8AttributeOutput::CharBackground( const SvxBrushItem& rBrush )
1659 {
1660     if( m_rWW8Export.bWrtWW8 )   // nur WW8 kann ZeichenHintergrund
1661     {
1662         WW8_SHD aSHD;
1663 
1664         m_rWW8Export.TransBrush( rBrush.GetColor(), aSHD );
1665         // sprmCShd
1666         m_rWW8Export.InsUInt16( NS_sprm::LN_CShd );
1667         m_rWW8Export.InsUInt16( aSHD.GetValue() );
1668 
1669         //Quite a few unknowns, some might be transparency or something
1670         //of that nature...
1671         m_rWW8Export.InsUInt16( 0xCA71 );
1672         m_rWW8Export.pO->Insert( 10, m_rWW8Export.pO->Count() );
1673         m_rWW8Export.InsUInt32( 0xFF000000 );
1674         m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor().GetColor() ) );
1675         m_rWW8Export.InsUInt16( 0x0000);
1676     }
1677 }
1678 
TextINetFormat(const SwFmtINetFmt & rINet)1679 void WW8AttributeOutput::TextINetFormat( const SwFmtINetFmt& rINet )
1680 {
1681     if ( rINet.GetValue().Len() )
1682     {
1683         const sal_uInt16 nId = rINet.GetINetFmtId();
1684         const String& rStr = rINet.GetINetFmt();
1685         if ( rStr.Len() == 0 )
1686         {
1687             ASSERT( false, "WW8AttributeOutput::TextINetFormat(..) - missing unvisited character format at hyperlink attribute" );
1688         }
1689 
1690         const SwCharFmt* pFmt = IsPoolUserFmt( nId )
1691                         ? m_rWW8Export.pDoc->FindCharFmtByName( rStr )
1692                         : m_rWW8Export.pDoc->GetCharFmtFromPool( nId );
1693 
1694         if ( m_rWW8Export.bWrtWW8 )
1695             m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
1696         else
1697             m_rWW8Export.pO->Insert( 80, m_rWW8Export.pO->Count() );
1698 
1699         m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pFmt ) );
1700     }
1701 }
1702 
1703 // --> OD 2005-06-08 #i43956# - add optional parameter <pLinkStr>
1704 // It's needed to write the hyperlink data for a certain cross-reference
1705 // - it contains the name of the link target, which is a bookmark.
1706 // --> OD 2008-08-14 #158418# - add optional parameter <bIncludeEmptyPicLocation>
1707 // It is needed to write an empty picture location for page number field separators
InsertSpecialChar(WW8Export & rWrt,sal_uInt8 c,String * pLinkStr=0L,bool bIncludeEmptyPicLocation=false)1708 static void InsertSpecialChar( WW8Export& rWrt, sal_uInt8 c,
1709                                String* pLinkStr = 0L,
1710                                bool bIncludeEmptyPicLocation = false )
1711 {
1712     WW8Bytes aItems;
1713     rWrt.GetCurrentItems(aItems);
1714 
1715     if (c == 0x13)
1716         rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell());
1717     else
1718         rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.Count(),
1719             aItems.GetData());
1720 
1721     rWrt.WriteChar(c);
1722 
1723     // --> OD 2008-08-14 #158418#
1724     // store empty sprmCPicLocation for field separator
1725     if ( bIncludeEmptyPicLocation &&
1726          ( c == 0x13 || c == 0x14 || c == 0x15 ) )
1727     {
1728         SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CPicLocation );
1729         SwWW8Writer::InsUInt32( aItems, 0x00000000 );
1730     }
1731     // <--
1732 
1733     // --> OD 2005-06-08 #i43956# - write hyperlink data and attributes
1734     if ( rWrt.bWrtWW8 && c == 0x01 && pLinkStr )
1735     {
1736         // write hyperlink data to data stream
1737         SvStream& rStrm = *rWrt.pDataStrm;
1738         // position of hyperlink data
1739         const sal_uInt32 nLinkPosInDataStrm = rStrm.Tell();
1740         // write empty header
1741         const sal_uInt16 nEmptyHdrLen = 0x44;
1742         sal_uInt8 aEmptyHeader[ nEmptyHdrLen ] = { 0 };
1743         aEmptyHeader[ 4 ] = 0x44;
1744         rStrm.Write( aEmptyHeader, nEmptyHdrLen );
1745         // writer fixed header
1746         const sal_uInt16 nFixHdrLen = 0x19;
1747         sal_uInt8 aFixHeader[ nFixHdrLen ] =
1748         {
1749             0x08, 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE,
1750             0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9,
1751             0x0B, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
1752             0x00,
1753         };
1754         rStrm.Write( aFixHeader, nFixHdrLen );
1755         // write reference string including length+1
1756         sal_uInt32 nStrLen( pLinkStr->Len() + 1 );
1757         SwWW8Writer::WriteLong( rStrm, nStrLen );
1758         SwWW8Writer::WriteString16( rStrm, *(pLinkStr), false );
1759         // write additional two NULL Bytes
1760         SwWW8Writer::WriteLong( rStrm, 0 );
1761         // write length of hyperlink data
1762         const sal_uInt32 nCurrPos = rStrm.Tell();
1763         rStrm.Seek( nLinkPosInDataStrm );
1764         SVBT32 nLen;
1765         UInt32ToSVBT32( nCurrPos - nLinkPosInDataStrm, nLen );
1766         rStrm.Write( nLen, 4 );
1767         rStrm.Seek( nCurrPos );
1768 
1769         // write attributes of hyperlink character 0x01
1770         SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish );
1771         aItems.Insert( (sal_uInt8)0x81, aItems.Count() );
1772         SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CPicLocation );
1773         SwWW8Writer::InsUInt32( aItems, nLinkPosInDataStrm );
1774         SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFData );
1775         aItems.Insert( (sal_uInt8)0x01, aItems.Count() );
1776     }
1777 
1778     //Technically we should probably Remove all attribs
1779     //here for the 0x13, 0x14, 0x15, but our import
1780     //is slightly lacking
1781     //aItems.Remove(0, aItems.Count());
1782     // fSpec-Attribute true
1783     if( rWrt.bWrtWW8 )
1784     {
1785         SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFSpec );
1786         aItems.Insert( 1, aItems.Count() );
1787     }
1788     else
1789     {
1790         aItems.Insert( 117, aItems.Count() ); //sprmCFSpec
1791         aItems.Insert( 1, aItems.Count() );
1792     }
1793 
1794     rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.Count(),
1795         aItems.GetData());
1796 }
1797 
lcl_GetExpandedField(const SwField & rFld)1798 String lcl_GetExpandedField(const SwField &rFld)
1799 {
1800     String sRet(rFld.ExpandField(true));
1801 
1802     //replace LF 0x0A with VT 0x0B
1803     sRet.SearchAndReplaceAll(0x0A, 0x0B);
1804 
1805     return sRet;
1806 }
1807 
CurrentFieldPlc() const1808 WW8_WrPlcFld* WW8Export::CurrentFieldPlc() const
1809 {
1810     WW8_WrPlcFld* pFldP = NULL;
1811     switch (nTxtTyp)
1812     {
1813         case TXT_MAINTEXT:
1814             pFldP = pFldMain;
1815             break;
1816         case TXT_HDFT:
1817             pFldP = pFldHdFt;
1818             break;
1819         case TXT_FTN:
1820             pFldP = pFldFtn;
1821             break;
1822         case TXT_EDN:
1823             pFldP = pFldEdn;
1824             break;
1825         case TXT_ATN:
1826             pFldP = pFldAtn;
1827             break;
1828         case TXT_TXTBOX:
1829             pFldP = pFldTxtBxs;
1830             break;
1831         case TXT_HFTXTBOX:
1832             pFldP = pFldHFTxtBxs;
1833             break;
1834         default:
1835             ASSERT( !this, "was ist das fuer ein SubDoc-Type?" );
1836     }
1837     return pFldP;
1838 }
1839 
OutputField(const SwField * pFld,ww::eField eFldType,const String & rFldCmd,sal_uInt8 nMode)1840 void WW8Export::OutputField( const SwField* pFld, ww::eField eFldType,
1841     const String& rFldCmd, sal_uInt8 nMode )
1842 {
1843     bool bUnicode = IsUnicode();
1844     WW8_WrPlcFld* pFldP = CurrentFieldPlc();
1845 
1846     const bool bIncludeEmptyPicLocation = ( eFldType == ww::ePAGE );
1847     if (WRITEFIELD_START & nMode)
1848     {
1849         sal_uInt8 aFld13[2] = { 0x13, 0x00 };  // will change
1850         //#i3958#, Needed to make this field work correctly in Word 2000
1851         if (eFldType == ww::eSHAPE)
1852             aFld13[0] |= 0x80;
1853         aFld13[1] = static_cast< sal_uInt8 >(eFldType);  // Typ nachtragen
1854         pFldP->Append( Fc2Cp( Strm().Tell() ), aFld13 );
1855         InsertSpecialChar( *this, 0x13, 0, bIncludeEmptyPicLocation );
1856     }
1857     if (WRITEFIELD_CMD_START & nMode)
1858     {
1859         if (bUnicode)
1860             SwWW8Writer::WriteString16(Strm(), rFldCmd, false);
1861         else
1862         {
1863             SwWW8Writer::WriteString8(Strm(), rFldCmd, false,
1864                 RTL_TEXTENCODING_MS_1252);
1865         }
1866         // write hyperlink character including attributes and
1867         // corresponding binary data for certain reference fields.
1868         bool bHandleBookmark = false;
1869 
1870         if (pFld)
1871         {
1872             if (pFld->GetTyp()->Which() == RES_GETREFFLD &&
1873                 ( eFldType == ww::ePAGEREF || eFldType == ww::eREF ||
1874                   eFldType == ww::eNOTEREF || eFldType == ww::eFOOTREF ))
1875                 bHandleBookmark = true;
1876         }
1877 
1878         if ( bHandleBookmark )
1879         {
1880             // retrieve reference destionation - the name of the bookmark
1881             String aLinkStr;
1882             const sal_uInt16 nSubType = pFld->GetSubType();
1883             const SwGetRefField& rRFld = *(static_cast<const SwGetRefField*>(pFld));
1884             if ( nSubType == REF_SETREFATTR ||
1885                  nSubType == REF_BOOKMARK )
1886             {
1887                 aLinkStr = GetBookmarkName( nSubType, &rRFld.GetSetRefName(), 0 );
1888             }
1889             else if ( nSubType == REF_FOOTNOTE ||
1890                       nSubType == REF_ENDNOTE )
1891             {
1892                 aLinkStr = GetBookmarkName( nSubType, 0, rRFld.GetSeqNo() );
1893             }
1894             else if ( nSubType == REF_SEQUENCEFLD )
1895             {
1896                 aLinkStr = pFld->GetPar2();
1897             }
1898             // insert hyperlink character including attributes and data.
1899             InsertSpecialChar( *this, 0x01, &aLinkStr );
1900         }
1901     }
1902     if (WRITEFIELD_CMD_END & nMode)
1903     {
1904         static const sal_uInt8 aFld14[2] = { 0x14, 0xff };
1905         pFldP->Append( Fc2Cp( Strm().Tell() ), aFld14 );
1906         pFldP->ResultAdded();
1907         InsertSpecialChar( *this, 0x14, 0, bIncludeEmptyPicLocation );
1908     }
1909     if (WRITEFIELD_END & nMode)
1910     {
1911         String sOut;
1912         if( pFld )
1913             sOut = lcl_GetExpandedField(*pFld);
1914         else
1915             sOut = rFldCmd;
1916         if( sOut.Len() )
1917         {
1918             if( bUnicode )
1919                 SwWW8Writer::WriteString16(Strm(), sOut, false);
1920             else
1921             {
1922                 SwWW8Writer::WriteString8(Strm(), sOut, false,
1923                     RTL_TEXTENCODING_MS_1252);
1924             }
1925 
1926             if (pFld)
1927             {
1928                 if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
1929                     eFldType == ww::eFORMTEXT)
1930                 {
1931                     sal_uInt8 aArr[12];
1932                     sal_uInt8 *pArr = aArr;
1933 
1934                     if ( bWrtWW8 )
1935                     {
1936                         Set_UInt16( pArr, NS_sprm::LN_CPicLocation );
1937                         Set_UInt32( pArr, 0x0 );
1938 
1939                         Set_UInt16( pArr, NS_sprm::LN_CFSpec );
1940                         Set_UInt8( pArr, 1 );
1941 
1942                         Set_UInt16( pArr, NS_sprm::LN_CFNoProof );
1943                         Set_UInt8( pArr, 1 );
1944                     }
1945                     else
1946                     {
1947                         Set_UInt8(pArr, 0x68); //sprmCPicLocation
1948                         Set_UInt32(pArr, 0x0);
1949 
1950                         Set_UInt8( pArr, 117 ); //sprmCFSpec
1951                         Set_UInt8( pArr, 1 );
1952                     }
1953                     pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
1954                 }
1955             }
1956         }
1957     }
1958     if (WRITEFIELD_CLOSE & nMode)
1959     {
1960         sal_uInt8 aFld15[2] = { 0x15, 0x80 };
1961 
1962         if (pFld)
1963         {
1964             if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
1965                 eFldType == ww::eFORMTEXT)
1966             {
1967                 sal_uInt16 nSubType = pFld->GetSubType();
1968 
1969                 if (nSubType == REF_SEQUENCEFLD)
1970                     aFld15[0] |= (0x4 << 5);
1971             }
1972         }
1973 
1974         pFldP->Append( Fc2Cp( Strm().Tell() ), aFld15 );
1975         InsertSpecialChar( *this, 0x15, 0, bIncludeEmptyPicLocation );
1976     }
1977 }
1978 
StartCommentOutput(const String & rName)1979 void WW8Export::StartCommentOutput(const String& rName)
1980 {
1981     String sStr(FieldString(ww::eQUOTE));
1982     sStr.APPEND_CONST_ASC("[");
1983     sStr += rName;
1984     sStr.APPEND_CONST_ASC("] ");
1985     OutputField(0, ww::eQUOTE, sStr, WRITEFIELD_START | WRITEFIELD_CMD_START);
1986 }
1987 
EndCommentOutput(const String & rName)1988 void WW8Export::EndCommentOutput(const String& rName)
1989 {
1990     String sStr(CREATE_CONST_ASC(" ["));
1991     sStr += rName;
1992     sStr.APPEND_CONST_ASC("] ");
1993     OutputField(0, ww::eQUOTE, sStr, WRITEFIELD_CMD_END | WRITEFIELD_END |
1994         WRITEFIELD_CLOSE);
1995 }
1996 
GetId(const SwTOXType & rTOXType)1997 sal_uInt16 MSWordExportBase::GetId( const SwTOXType& rTOXType )
1998 {
1999     void* p = (void*)&rTOXType;
2000     sal_uInt16 nRet = aTOXArr.GetPos( p );
2001     if( USHRT_MAX == nRet )
2002         aTOXArr.Insert( p, nRet = aTOXArr.Count() );
2003     return nRet;
2004 }
2005 
2006 // return values:  1 - no PageNum,
2007 //                 2 - TabStop before PageNum,
2008 //                 3 - Text before PageNum - rTxt hold the text
2009 //                 4 - no Text and no TabStop before PageNum
lcl_CheckForm(const SwForm & rForm,sal_uInt8 nLvl,String & rText)2010 int lcl_CheckForm( const SwForm& rForm, sal_uInt8 nLvl, String& rText )
2011 {
2012     int nRet = 4;
2013     rText.Erase();
2014 
2015     // #i21237#
2016     SwFormTokens aPattern = rForm.GetPattern(nLvl);
2017     SwFormTokens::iterator aIt = aPattern.begin();
2018     bool bPgNumFnd = false;
2019     FormTokenType eTType;
2020 
2021     // #i61362#
2022     if (! aPattern.empty())
2023     {
2024         // #i21237#
2025         while( ++aIt != aPattern.end() && !bPgNumFnd )
2026         {
2027             eTType = aIt->eTokenType;
2028 
2029             switch( eTType )
2030             {
2031             case TOKEN_PAGE_NUMS:
2032                 bPgNumFnd = true;
2033                 break;
2034 
2035             case TOKEN_TAB_STOP:
2036                 nRet = 2;
2037                 break;
2038             case TOKEN_TEXT:
2039                 nRet = 3;
2040                 rText = aIt->sText.Copy( 0, 5 ); // #i21237#
2041                 break;
2042 
2043             case TOKEN_LINK_START:
2044             case TOKEN_LINK_END:
2045                 break;
2046 
2047             default:
2048                 nRet = 4;
2049                 break;
2050             }
2051         }
2052 
2053         if( !bPgNumFnd )
2054             nRet = 1;
2055     }
2056 
2057     return nRet;
2058 }
2059 
lcl_IsHyperlinked(const SwForm & rForm,sal_uInt16 nTOXLvl)2060 bool lcl_IsHyperlinked(const SwForm& rForm, sal_uInt16 nTOXLvl)
2061 {
2062     bool bRes = false;
2063     for (sal_uInt16 nI = 1; nI < nTOXLvl; ++nI)
2064     {
2065         // #i21237#
2066         SwFormTokens aPattern = rForm.GetPattern(nI);
2067 
2068         if ( !aPattern.empty() )
2069         {
2070             SwFormTokens::iterator aIt = aPattern.begin();
2071 
2072             FormTokenType eTType;
2073 
2074             // #i21237#
2075             while ( ++aIt != aPattern.end() )
2076             {
2077                 eTType = aIt->eTokenType;
2078                 switch (eTType)
2079                 {
2080                 case TOKEN_LINK_START:
2081                 case TOKEN_LINK_END:
2082                     bRes = true;
2083                 break;
2084                 default:
2085                     ;
2086                 }
2087             }
2088         }
2089     }
2090     return bRes;
2091 }
2092 
StartTOX(const SwSection & rSect)2093 void AttributeOutputBase::StartTOX( const SwSection& rSect )
2094 {
2095     if ( const SwTOXBase* pTOX = rSect.GetTOXBase() )
2096     {
2097         static const sal_Char sEntryEnd[] = "\" ";
2098 
2099         ww::eField eCode = ww::eTOC;
2100         String sStr = pTOX->GetMSTOCExpression();
2101         if ( !sStr.Len() )
2102         {
2103             switch (pTOX->GetType())
2104             {
2105             case TOX_INDEX:
2106                 eCode = ww::eINDEX;
2107                 sStr = FieldString(eCode);
2108 
2109                 if (pTOX->GetTOXForm().IsCommaSeparated())
2110                     sStr.APPEND_CONST_ASC("\\r ");
2111 
2112                 if (nsSwTOIOptions::TOI_ALPHA_DELIMITTER & pTOX->GetOptions())
2113                     sStr.APPEND_CONST_ASC("\\h \"A\" ");
2114 
2115                 {
2116                     String aFillTxt;
2117                     for (sal_uInt8 n = 1; n <= 3; ++n)
2118                     {
2119                         String aTxt;
2120                         int nRet = ::lcl_CheckForm(pTOX->GetTOXForm(), n, aTxt);
2121 
2122                         if( 3 == nRet )
2123                             aFillTxt = aTxt;
2124                         else if ((4 == nRet) || (2 == nRet)) //#109414#
2125                             aFillTxt = '\t';
2126                         else
2127                             aFillTxt.Erase();
2128                     }
2129                     sStr.APPEND_CONST_ASC("\\e \"");
2130                     sStr += aFillTxt;
2131                     sStr.AppendAscii(sEntryEnd);
2132                 }
2133                 break;
2134 
2135                 //      case TOX_AUTHORITIES:   eCode = eTOA; sStr = ???; break;
2136 
2137             case TOX_ILLUSTRATIONS:
2138             case TOX_OBJECTS:
2139             case TOX_TABLES:
2140                 if (!pTOX->IsFromObjectNames())
2141                 {
2142                     sStr = FieldString(eCode);
2143 
2144                     sStr.APPEND_CONST_ASC("\\c \"");
2145                     sStr += pTOX->GetSequenceName();
2146                     sStr.AppendAscii(sEntryEnd);
2147 
2148                     String aTxt;
2149                     int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), 1, aTxt );
2150                     if (1 == nRet)
2151                         sStr.APPEND_CONST_ASC("\\n ");
2152                     else if( 3 == nRet || 4 == nRet )
2153                     {
2154                         sStr.APPEND_CONST_ASC("\\p \"");
2155                         sStr += aTxt;
2156                         sStr.AppendAscii(sEntryEnd);
2157                     }
2158                 }
2159                 break;
2160 
2161                 //      case TOX_USER:
2162                 //      case TOX_CONTENT:
2163             default:
2164                 {
2165                     sStr = FieldString(eCode);
2166 
2167                     String sTOption;
2168                     sal_uInt16 n, nTOXLvl = pTOX->GetLevel();
2169                     if( !nTOXLvl )
2170                         ++nTOXLvl;
2171 
2172                     if( nsSwTOXElement::TOX_MARK & pTOX->GetCreateType() )
2173                     {
2174                         sStr.APPEND_CONST_ASC( "\\f " );
2175 
2176                         if( TOX_USER == pTOX->GetType() )
2177                         {
2178                             sStr += '\"';
2179                             sStr += (sal_Char)( 'A' + GetExport( ).GetId( *pTOX->GetTOXType() ) );
2180                             sStr.AppendAscii( sEntryEnd );
2181                         }
2182 
2183                         if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() )
2184                         {
2185                             const int nMinLvl = nTOXLvl;
2186                             if ( nMinLvl > 0 )
2187                             {
2188                                 int nTmpLvl = nMinLvl;
2189                                 if (nTmpLvl > WW8ListManager::nMaxLevel)
2190                                     nTmpLvl = WW8ListManager::nMaxLevel;
2191 
2192                                 sStr.APPEND_CONST_ASC( "\\o \"1-" );
2193                                 sStr += String::CreateFromInt32( nTmpLvl );
2194                                 sStr.AppendAscii(sEntryEnd);
2195 
2196                             }
2197                         }
2198 
2199 
2200                         if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() )
2201                         {
2202                             // Take the TOC value of the max level to evaluate to as
2203                             // the starting point for the \o flag, but reduce it to the
2204                             // value of the highest outline level filled by a *standard*
2205                             // Heading 1 - 9 style because \o "Builds a table of
2206                             // contents from paragraphs formatted with built-in heading
2207                             // styles". And afterward fill in any outline styles left
2208                             // uncovered by that range to the \t flag
2209                             //
2210                             // i.e. for
2211                             // Heading 1
2212                             // Heading 2
2213                             // custom-style
2214                             // Heading 4
2215                             // output
2216                             // \o 1-2 \tcustom-style,3,Heading 3,4
2217 
2218                             // Search over all the outline styles used and figure out
2219                             // what is the minimum outline level (if any) filled by a
2220                             // non-standard style for that level, i.e. ignore headline
2221                             // styles 1-9 and find the lowest valid outline level
2222                             sal_uInt8 nPosOfLowestNonStandardLvl = MAXLEVEL;
2223                             const SwTxtFmtColls& rColls = *GetExport().pDoc->GetTxtFmtColls();
2224                             for( n = rColls.Count(); n; )
2225                             {
2226                                 const SwTxtFmtColl* pColl = rColls[ --n ];
2227                                 sal_uInt16 nPoolId = pColl->GetPoolFmtId();
2228                                 if (
2229                                     //Is a Non-Standard Outline Style
2230                                     (RES_POOLCOLL_HEADLINE1 > nPoolId || RES_POOLCOLL_HEADLINE9 < nPoolId) &&
2231                                     //Has a valid outline level
2232                                     (pColl->IsAssignedToListLevelOfOutlineStyle()) &&
2233                                     // Is less than the lowest known non-standard level
2234                                     (pColl->GetAssignedOutlineStyleLevel() < nPosOfLowestNonStandardLvl)
2235                                     )
2236                                 {
2237                                     nPosOfLowestNonStandardLvl = ::sal::static_int_cast<sal_uInt8>(pColl->GetAssignedOutlineStyleLevel());
2238                                 }
2239                             }
2240 
2241                             sal_uInt8 nMaxMSAutoEvaluate = nPosOfLowestNonStandardLvl < nTOXLvl ? nPosOfLowestNonStandardLvl : (sal_uInt8)nTOXLvl;
2242 
2243                             //output \o 1-X where X is the highest normal outline style to be included in the toc
2244                             if ( nMaxMSAutoEvaluate )
2245                             {
2246                                 if (nMaxMSAutoEvaluate > WW8ListManager::nMaxLevel)
2247                                     nMaxMSAutoEvaluate = WW8ListManager::nMaxLevel;
2248 
2249                                 sStr.APPEND_CONST_ASC( "\\o \"1-" );
2250                                 sStr += String::CreateFromInt32( nMaxMSAutoEvaluate );
2251                                 sStr.AppendAscii(sEntryEnd);
2252                             }
2253 
2254                             //collect up any other styles in the writer TOC which will
2255                             //not already appear in the MS TOC and place then into the
2256                             //\t option
2257                             if( nMaxMSAutoEvaluate < nTOXLvl )
2258                             {
2259                                 // collect this templates into the \t otion
2260                                 for( n = rColls.Count(); n;)
2261                                 {
2262                                     const SwTxtFmtColl* pColl = rColls[ --n ];
2263                                     if (!pColl->IsAssignedToListLevelOfOutlineStyle())
2264                                         continue;
2265                                     sal_uInt8 nTestLvl =  ::sal::static_int_cast<sal_uInt8>(pColl->GetAssignedOutlineStyleLevel());
2266                                     if (nTestLvl < nTOXLvl && nTestLvl >= nMaxMSAutoEvaluate)
2267                                     {
2268                                         if( sTOption.Len() )
2269                                             sTOption += ',';
2270                                         (( sTOption += pColl->GetName() ) += ',' )
2271                                             += String::CreateFromInt32( nTestLvl + 1 );
2272                                     }
2273                                 }
2274                             }
2275                         }
2276 
2277                         if( nsSwTOXElement::TOX_TEMPLATE & pTOX->GetCreateType() )
2278                             // --> OD 2009-02-27 #i99641#
2279                             // Consider additional styles regardless of TOX-outlinelevel
2280                             for( n = 0; n < MAXLEVEL; ++n )
2281                                 // <--
2282                             {
2283                                 const String& rStyles = pTOX->GetStyleNames( n );
2284                                 if( rStyles.Len() )
2285                                 {
2286                                     xub_StrLen nPos = 0;
2287                                     String sLvl( ',' );
2288                                     sLvl += String::CreateFromInt32( n + 1 );
2289                                     do {
2290                                         String sStyle( rStyles.GetToken( 0,
2291                                             TOX_STYLE_DELIMITER, nPos ));
2292                                         if( sStyle.Len() )
2293                                         {
2294                                             SwTxtFmtColl* pColl = GetExport().pDoc->FindTxtFmtCollByName(sStyle);
2295                                             if (!pColl->IsAssignedToListLevelOfOutlineStyle() || pColl->GetAssignedOutlineStyleLevel() < nTOXLvl)
2296                                             {
2297                                                 if( sTOption.Len() )
2298                                                     sTOption += ',';
2299                                                 ( sTOption += sStyle ) += sLvl;
2300                                             }
2301                                         }
2302                                     } while( STRING_NOTFOUND != nPos );
2303                                 }
2304                             }
2305 
2306                             {
2307                                 String aFillTxt;
2308                                 sal_uInt8 nNoPgStt = MAXLEVEL, nNoPgEnd = MAXLEVEL;
2309                                 bool bFirstFillTxt = true, bOnlyText = true;
2310                                 for( n = 0; n < nTOXLvl; ++n )
2311                                 {
2312                                     String aTxt;
2313                                     int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(),
2314                                         static_cast< sal_uInt8 >(n+1), aTxt );
2315                                     if( 1 == nRet )
2316                                     {
2317                                         bOnlyText = false;
2318                                         if( MAXLEVEL == nNoPgStt )
2319                                             nNoPgStt = static_cast< sal_uInt8 >(n+1);
2320                                     }
2321                                     else
2322                                     {
2323                                         if( MAXLEVEL != nNoPgStt &&
2324                                             MAXLEVEL == nNoPgEnd )
2325                                             nNoPgEnd = sal_uInt8(n);
2326 
2327                                         bOnlyText = bOnlyText && 3 == nRet;
2328                                         if( 3 == nRet || 4 == nRet )
2329                                         {
2330                                             if( bFirstFillTxt )
2331                                                 aFillTxt = aTxt;
2332                                             else if( aFillTxt != aTxt )
2333                                                 aFillTxt.Erase();
2334                                             bFirstFillTxt = false;
2335                                         }
2336                                     }
2337                                 }
2338                                 if( MAXLEVEL != nNoPgStt )
2339                                 {
2340                                     if (WW8ListManager::nMaxLevel < nNoPgEnd)
2341                                         nNoPgEnd = WW8ListManager::nMaxLevel;
2342                                     sStr.APPEND_CONST_ASC( "\\n " );
2343                                     sStr += String::CreateFromInt32( nNoPgStt );
2344                                     sStr += '-';
2345                                     sStr += String::CreateFromInt32( nNoPgEnd  );
2346                                     sStr += ' ';
2347                                 }
2348                                 if( bOnlyText )
2349                                 {
2350                                     sStr.APPEND_CONST_ASC( "\\p \"" );
2351                                     sStr += aFillTxt;
2352                                     sStr.AppendAscii(sEntryEnd);
2353                                 }
2354                             }
2355 
2356                             if( sTOption.Len() )
2357                             {
2358                                 sStr.APPEND_CONST_ASC( "\\t \"" );
2359                                 sStr += sTOption;
2360                                 sStr.AppendAscii(sEntryEnd);
2361                             }
2362 
2363                             if (lcl_IsHyperlinked(pTOX->GetTOXForm(), nTOXLvl))
2364                                 sStr.APPEND_CONST_ASC("\\h");
2365                     }
2366                     break;
2367                 }
2368             }
2369         }
2370 
2371         if ( sStr.Len() )
2372         {
2373             GetExport( ).bInWriteTOX = true;
2374             GetExport( ).OutputField( 0, eCode, sStr,
2375                                       WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
2376         }
2377     }
2378 
2379     GetExport( ).bStartTOX = false;
2380 }
2381 
EndTOX(const SwSection & rSect,bool bCareEnd)2382 void AttributeOutputBase::EndTOX( const SwSection& rSect,bool bCareEnd )
2383 {
2384     const SwTOXBase* pTOX = rSect.GetTOXBase();
2385     if ( pTOX )
2386     {
2387         ww::eField eCode = TOX_INDEX == pTOX->GetType() ? ww::eINDEX : ww::eTOC;
2388         GetExport( ).OutputField( 0, eCode, aEmptyStr, WRITEFIELD_CLOSE );
2389     }
2390     GetExport( ).bInWriteTOX = false;
2391     if (bCareEnd)
2392         OnTOXEnding();
2393 }
2394 
GetNumberFmt(const SwField & rFld,String & rStr)2395 bool MSWordExportBase::GetNumberFmt(const SwField& rFld, String& rStr)
2396 {
2397     // Returns a date or time format string by using the US NfKeywordTable
2398     bool bHasFmt = false;
2399     SvNumberFormatter* pNFmtr = pDoc->GetNumberFormatter();
2400     sal_uInt32 nFmtIdx = rFld.GetFormat();
2401     const SvNumberformat* pNumFmt = pNFmtr->GetEntry( nFmtIdx );
2402     if( pNumFmt )
2403     {
2404         sal_uInt16 nLng = rFld.GetLanguage();
2405         LocaleDataWrapper aLocDat(pNFmtr->GetServiceManager(),
2406                                   MsLangId::convertLanguageToLocale(nLng));
2407 
2408         String sFmt(pNumFmt->GetMappedFormatstring(GetNfKeywordTable(),
2409             aLocDat));
2410 
2411         if (sFmt.Len())
2412         {
2413             sw::ms::SwapQuotesInField(sFmt);
2414 
2415             rStr.APPEND_CONST_ASC( "\\@\"" );
2416             rStr += sFmt;
2417             rStr.APPEND_CONST_ASC( "\" " );
2418             bHasFmt = true;
2419         }
2420     }
2421     return bHasFmt;
2422 }
2423 
GetNumberPara(String & rStr,const SwField & rFld)2424 void AttributeOutputBase::GetNumberPara( String& rStr, const SwField& rFld )
2425 {
2426     switch(rFld.GetFormat())
2427     {
2428         case SVX_NUM_CHARS_UPPER_LETTER:
2429         case SVX_NUM_CHARS_UPPER_LETTER_N:
2430             rStr.APPEND_CONST_ASC( "\\*ALPHABETIC ");
2431             break;
2432         case SVX_NUM_CHARS_LOWER_LETTER:
2433         case SVX_NUM_CHARS_LOWER_LETTER_N:
2434             rStr.APPEND_CONST_ASC("\\*alphabetic ");
2435             break;
2436         case SVX_NUM_ROMAN_UPPER:
2437             rStr.APPEND_CONST_ASC("\\*ROMAN ");
2438             break;
2439         case SVX_NUM_ROMAN_LOWER:
2440             rStr.APPEND_CONST_ASC("\\*roman ");
2441             break;
2442         default:
2443             ASSERT(rFld.GetFormat() == SVX_NUM_ARABIC,
2444                 "Unknown numbering type exported as default\n");
2445         case SVX_NUM_ARABIC:
2446             rStr.APPEND_CONST_ASC("\\*Arabic ");
2447             break;
2448         case SVX_NUM_PAGEDESC:
2449             //Nothing, use word's default
2450             break;
2451     }
2452 }
2453 
WritePostItBegin(WW8Bytes * pOut)2454 void WW8Export::WritePostItBegin( WW8Bytes* pOut )
2455 {
2456     sal_uInt8 aArr[ 3 ];
2457     sal_uInt8* pArr = aArr;
2458 
2459     // sprmCFSpec true
2460     if( bWrtWW8 )
2461         Set_UInt16( pArr, NS_sprm::LN_CFSpec );
2462     else
2463         Set_UInt8( pArr, 117 ); //sprmCFSpec
2464     Set_UInt8( pArr, 1 );
2465 
2466     pChpPlc->AppendFkpEntry( Strm().Tell() );
2467     WriteChar( 0x05 );              // Annotation reference
2468 
2469     if( pOut )
2470         pOut->Insert( aArr, static_cast< sal_uInt16 >(pArr - aArr), pOut->Count() );
2471     else
2472         pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
2473 }
2474 
FieldString(ww::eField eIndex)2475 String FieldString(ww::eField eIndex)
2476 {
2477     String sRet(CREATE_CONST_ASC("  "));
2478     if (const char *pField = ww::GetEnglishFieldName(eIndex))
2479         sRet.InsertAscii(pField, 1);
2480     return sRet;
2481 }
2482 
HiddenField(const SwField & rFld)2483 void WW8AttributeOutput::HiddenField( const SwField& rFld )
2484 {
2485     String sExpand(rFld.GetPar2());
2486 
2487     //replace LF 0x0A with VT 0x0B
2488     sExpand.SearchAndReplaceAll(0x0A, 0x0B);
2489     m_rWW8Export.pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell());
2490     if (m_rWW8Export.IsUnicode())
2491     {
2492         SwWW8Writer::WriteString16(m_rWW8Export.Strm(), sExpand, false);
2493         static sal_uInt8 aArr[] =
2494         {
2495             0x3C, 0x08, 0x1
2496         };
2497         m_rWW8Export.pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell(), sizeof(aArr), aArr);
2498     }
2499     else
2500     {
2501         SwWW8Writer::WriteString8(m_rWW8Export.Strm(), sExpand, false,
2502             RTL_TEXTENCODING_MS_1252);
2503         static sal_uInt8 aArr[] =
2504         {
2505             92, 0x1
2506         };
2507         m_rWW8Export.pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell(), sizeof(aArr), aArr);
2508     }
2509 }
2510 
SetField(const SwField & rFld,ww::eField eType,const String & rCmd)2511 void WW8AttributeOutput::SetField( const SwField& rFld, ww::eField eType, const String& rCmd )
2512 {
2513     const SwSetExpField* pSet=(const SwSetExpField*)(&rFld);
2514     const String &rVar = pSet->GetPar2();
2515 
2516     sal_uLong nFrom = m_rWW8Export.Fc2Cp(m_rWW8Export.Strm().Tell());
2517 
2518     GetExport().OutputField(&rFld, eType, rCmd, WRITEFIELD_START |
2519         WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
2520 
2521     /*
2522     Is there a bookmark at the start position of this field, if so
2523     move it to the 0x14 of the result of the field.  This is what word
2524     does. MoveFieldMarks moves any bookmarks at this position to
2525     the beginning of the field result, and marks the bookmark as a
2526     fieldbookmark which is to be ended before the field end mark
2527     instead of after it like a normal bookmark.
2528     */
2529     m_rWW8Export.MoveFieldMarks(nFrom,m_rWW8Export.Fc2Cp(m_rWW8Export.Strm().Tell()));
2530 
2531     if (rVar.Len())
2532     {
2533         if (m_rWW8Export.IsUnicode())
2534             SwWW8Writer::WriteString16(m_rWW8Export.Strm(), rVar, false);
2535         else
2536         {
2537             SwWW8Writer::WriteString8(m_rWW8Export.Strm(), rVar, false,
2538                 RTL_TEXTENCODING_MS_1252);
2539         }
2540     }
2541     GetExport().OutputField(&rFld, eType, rCmd, WRITEFIELD_CLOSE);
2542 }
2543 
PostitField(const SwField * pFld)2544 void WW8AttributeOutput::PostitField( const SwField* pFld )
2545 {
2546     const SwPostItField *pPFld = (const SwPostItField*)pFld;
2547     m_rWW8Export.pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pPFld );
2548     m_rWW8Export.WritePostItBegin( m_rWW8Export.pO );
2549 }
2550 
DropdownField(const SwField * pFld)2551 bool WW8AttributeOutput::DropdownField( const SwField* pFld )
2552 {
2553     bool bExpand = true;
2554     if ( m_rWW8Export.bWrtWW8 )
2555     {
2556         const SwDropDownField& rFld2 = *(SwDropDownField*)pFld;
2557         uno::Sequence<rtl::OUString> aItems =
2558             rFld2.GetItemSequence();
2559         GetExport().DoComboBox(rFld2.GetName(),
2560                            rFld2.GetHelp(),
2561                            rFld2.GetToolTip(),
2562                            rFld2.GetSelectedItem(), aItems);
2563         bExpand = false;
2564     }
2565     return bExpand;
2566 }
2567 
RefField(const SwField & rFld,const String & rRef)2568 void WW8AttributeOutput::RefField( const SwField &rFld, const String &rRef)
2569 {
2570     String sStr( FieldString( ww::eREF ) );
2571     sStr.APPEND_CONST_ASC( "\"" );
2572     sStr += rRef;
2573     sStr.APPEND_CONST_ASC( "\" " );
2574     m_rWW8Export.OutputField( &rFld, ww::eREF, sStr, WRITEFIELD_START |
2575         WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
2576     String sVar = lcl_GetExpandedField( rFld );
2577     if ( sVar.Len() )
2578     {
2579         if ( m_rWW8Export.IsUnicode() )
2580             SwWW8Writer::WriteString16( m_rWW8Export.Strm(), sVar, false );
2581         else
2582         {
2583             SwWW8Writer::WriteString8( m_rWW8Export.Strm(), sVar, false,
2584                 RTL_TEXTENCODING_MS_1252 );
2585         }
2586     }
2587     m_rWW8Export.OutputField( &rFld, ww::eREF, sStr, WRITEFIELD_CLOSE );
2588 }
2589 
WriteExpand(const SwField * pFld)2590 void WW8AttributeOutput::WriteExpand( const SwField* pFld )
2591 {
2592     String sExpand( lcl_GetExpandedField( *pFld ) );
2593     if ( m_rWW8Export.IsUnicode() )
2594         SwWW8Writer::WriteString16( m_rWW8Export.Strm(), sExpand, false );
2595     else
2596     {
2597         SwWW8Writer::WriteString8( m_rWW8Export.Strm(), sExpand, false,
2598             RTL_TEXTENCODING_MS_1252 );
2599     }
2600 }
2601 
TextField(const SwFmtFld & rField)2602 void AttributeOutputBase::TextField( const SwFmtFld& rField )
2603 {
2604     const SwField* pFld = rField.GetField();
2605     String sStr;        // fuer optionale Parameter
2606     bool bWriteExpand = false;
2607     const sal_uInt16 nSubType = pFld->GetSubType();
2608 
2609     switch (pFld->GetTyp()->Which())
2610     {
2611     case RES_GETEXPFLD:
2612         if (nSubType == nsSwGetSetExpType::GSE_STRING)
2613         {
2614             const SwGetExpField *pGet=(const SwGetExpField*)(pFld);
2615             RefField( *pGet, pGet->GetFormula() );
2616         }
2617         else
2618             bWriteExpand = true;
2619         break;
2620     case RES_SETEXPFLD:
2621         if (nsSwGetSetExpType::GSE_SEQ == nSubType)
2622         {
2623             sStr = FieldString(ww::eSEQ);
2624             sStr.APPEND_CONST_ASC("\"");
2625             sStr += pFld->GetTyp()->GetName();
2626             sStr.APPEND_CONST_ASC( "\" " );
2627 
2628             GetNumberPara( sStr, *pFld );
2629             GetExport().OutputField(pFld, ww::eSEQ, sStr);
2630         }
2631         else if (nSubType & nsSwGetSetExpType::GSE_STRING)
2632         {
2633             bool bShowAsWell = false;
2634             ww::eField eFieldNo;
2635             const SwSetExpField *pSet=(const SwSetExpField*)(pFld);
2636             const String &rVar = pSet->GetPar2();
2637             if (pSet->GetInputFlag())
2638             {
2639                 sStr = FieldString(ww::eASK);
2640                 sStr.APPEND_CONST_ASC("\"");
2641                 sStr += pSet->GetPar1();
2642                 sStr.APPEND_CONST_ASC( "\" " );
2643                 sStr += pSet->GetPromptText();
2644                 sStr.APPEND_CONST_ASC( " \\d " );
2645                 sStr += rVar;
2646                 eFieldNo = ww::eASK;
2647             }
2648             else
2649             {
2650                 sStr = FieldString(ww::eSET);
2651                 sStr += pSet->GetPar1();
2652                 sStr.APPEND_CONST_ASC(" \"");
2653                 sStr += rVar;
2654                 sStr.APPEND_CONST_ASC("\" ");
2655                 eFieldNo = ww::eSET;
2656                 bShowAsWell = (nSubType & nsSwExtendedSubType::SUB_INVISIBLE) ? false : true;
2657             }
2658 
2659             SetField( *pFld, eFieldNo, sStr );
2660 
2661             if (bShowAsWell)
2662                 RefField( *pSet, pSet->GetPar1() );
2663         }
2664         else
2665             bWriteExpand = true;
2666         break;
2667     case RES_PAGENUMBERFLD:
2668         sStr = FieldString(ww::ePAGE);
2669         GetNumberPara(sStr, *pFld);
2670         GetExport().OutputField(pFld, ww::ePAGE, sStr);
2671         break;
2672     case RES_FILENAMEFLD:
2673         sStr = FieldString(ww::eFILENAME);
2674         if (pFld->GetFormat() == FF_PATHNAME)
2675             sStr.APPEND_CONST_ASC("\\p ");
2676         GetExport().OutputField(pFld, ww::eFILENAME, sStr);
2677         break;
2678     case RES_DBNAMEFLD:
2679         {
2680             sStr = FieldString(ww::eDATABASE);
2681             SwDBData aData = GetExport().pDoc->GetDBData();
2682             sStr += String(aData.sDataSource);
2683             sStr += DB_DELIM;
2684             sStr += String(aData.sCommand);
2685             GetExport().OutputField(pFld, ww::eDATABASE, sStr);
2686         }
2687         break;
2688     case RES_AUTHORFLD:
2689         {
2690             ww::eField eFld =
2691                 (AF_SHORTCUT & nSubType ? ww::eUSERINITIALS : ww::eUSERNAME);
2692             GetExport().OutputField(pFld, eFld, FieldString(eFld));
2693         }
2694         break;
2695     case RES_TEMPLNAMEFLD:
2696         GetExport().OutputField(pFld, ww::eTEMPLATE, FieldString(ww::eTEMPLATE));
2697         break;
2698     case RES_DOCINFOFLD:    // Last printed, last edited,...
2699         if( DI_SUB_FIXED & nSubType )
2700             bWriteExpand = true;
2701         else
2702         {
2703             ww::eField eFld(ww::eNONE);
2704             switch (0xff & nSubType)
2705             {
2706                 case DI_TITEL:
2707                     eFld = ww::eTITLE;
2708                     break;
2709                 case DI_THEMA:
2710                     eFld = ww::eSUBJECT;
2711                     break;
2712                 case DI_KEYS:
2713                     eFld = ww::eKEYWORDS;
2714                     break;
2715                 case DI_COMMENT:
2716                     eFld = ww::eCOMMENTS;
2717                     break;
2718                 case DI_DOCNO:
2719                     eFld = ww::eREVNUM;
2720                     break;
2721                 case DI_CREATE:
2722                     if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
2723                         eFld = ww::eAUTHOR;
2724                     else if (GetExport().GetNumberFmt(*pFld, sStr))
2725                         eFld = ww::eCREATEDATE;
2726                     break;
2727 
2728                 case DI_CHANGE:
2729                     if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
2730                         eFld = ww::eLASTSAVEDBY;
2731                     else if (GetExport().GetNumberFmt(*pFld, sStr))
2732                         eFld = ww::eSAVEDATE;
2733                     break;
2734 
2735                 case DI_PRINT:
2736                     if (DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK) &&
2737                         GetExport().GetNumberFmt(*pFld, sStr))
2738                         eFld = ww::ePRINTDATE;
2739                     break;
2740                 case DI_EDIT:
2741                     if( DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK ) &&
2742                         GetExport().GetNumberFmt( *pFld, sStr ))
2743                         eFld = ww::eSAVEDATE;
2744                     break;
2745                 case DI_CUSTOM:
2746                     eFld = ww::eDOCPROPERTY;
2747                     {
2748                         static String sQuotes('\"');
2749                         const SwDocInfoField * pDocInfoField =
2750                         dynamic_cast<const SwDocInfoField *> (pFld);
2751 
2752                         if (pDocInfoField != NULL)
2753                         {
2754                             String sFieldname = pDocInfoField->GetFieldName();
2755                             xub_StrLen nIndex = sFieldname.Search(':');
2756 
2757                             if (nIndex != sFieldname.Len())
2758                                 sFieldname = sFieldname.Copy(nIndex + 1);
2759 
2760                             sStr.Insert(sQuotes);
2761                             sStr.Insert(sFieldname);
2762                             sStr.Insert(sQuotes);
2763                         }
2764                     }
2765                     break;
2766                 default:
2767                     break;
2768             }
2769 
2770             if (eFld != ww::eNONE)
2771             {
2772                 sStr.Insert(FieldString(eFld), 0);
2773                 GetExport().OutputField(pFld, eFld, sStr);
2774             }
2775             else
2776                 bWriteExpand = true;
2777         }
2778         break;
2779     case RES_DATETIMEFLD:
2780         if (FIXEDFLD & nSubType || !GetExport().GetNumberFmt(*pFld, sStr))
2781             bWriteExpand = true;
2782         else
2783         {
2784             ww::eField eFld = (DATEFLD & nSubType) ? ww::eDATE : ww::eTIME;
2785             sStr.Insert(FieldString(eFld), 0);
2786             GetExport().OutputField(pFld, eFld, sStr);
2787         }
2788         break;
2789     case RES_DOCSTATFLD:
2790         {
2791             ww::eField eFld = ww::eNONE;
2792 
2793             switch (nSubType)
2794             {
2795                 case DS_PAGE:
2796                     eFld = ww::eNUMPAGE;
2797                     break;
2798                 case DS_WORD:
2799                     eFld = ww::eNUMWORDS;
2800                     break;
2801                 case DS_CHAR:
2802                     eFld = ww::eNUMCHARS;
2803                     break;
2804             }
2805 
2806             if (eFld != ww::eNONE)
2807             {
2808                 sStr = FieldString(eFld);
2809                 GetNumberPara(sStr, *pFld);
2810                 GetExport().OutputField(pFld, eFld, sStr);
2811             }
2812             else
2813                 bWriteExpand = true;
2814         }
2815         break;
2816     case RES_EXTUSERFLD:
2817         {
2818             ww::eField eFld = ww::eNONE;
2819             switch (0xFF & nSubType)
2820             {
2821                 case EU_FIRSTNAME:
2822                 case EU_NAME:
2823                     eFld = ww::eUSERNAME;
2824                     break;
2825                 case EU_SHORTCUT:
2826                     eFld = ww::eUSERINITIALS;
2827                     break;
2828                 case EU_STREET:
2829                 case EU_COUNTRY:
2830                 case EU_ZIP:
2831                 case EU_CITY:
2832                     eFld = ww::eUSERADDRESS;
2833                     break;
2834             }
2835 
2836             if (eFld != ww::eNONE)
2837             {
2838                 sStr = FieldString(eFld);
2839                 GetExport().OutputField(pFld, eFld, sStr);
2840             }
2841             else
2842                 bWriteExpand = true;
2843         }
2844         break;
2845     case RES_POSTITFLD:
2846         //Sadly only possible for word in main document text
2847         if (GetExport().nTxtTyp == TXT_MAINTEXT)
2848         {
2849             PostitField( pFld );
2850         }
2851         break;
2852     case RES_INPUTFLD:
2853         {
2854             const SwInputField * pInputField = dynamic_cast<const SwInputField *>(pFld);
2855 
2856             if (pInputField->isFormField())
2857                 GetExport().DoFormText(pInputField);
2858             else
2859             {
2860                 sStr = FieldString(ww::eFILLIN);
2861 
2862                 sStr.APPEND_CONST_ASC("\"");
2863                 sStr += pFld->GetPar2();
2864                 sStr += '\"';
2865 
2866                 GetExport().OutputField(pFld, ww::eFILLIN, sStr);
2867             }
2868         }
2869         break;
2870     case RES_GETREFFLD:
2871         {
2872             ww::eField eFld = ww::eNONE;
2873             const SwGetRefField& rRFld = *(SwGetRefField*)pFld;
2874             switch (nSubType)
2875             {
2876                 case REF_SETREFATTR:
2877                 case REF_BOOKMARK:
2878                     switch (pFld->GetFormat())
2879                     {
2880                         case REF_PAGE_PGDESC:
2881                         case REF_PAGE:
2882                             eFld = ww::ePAGEREF;
2883                             break;
2884                         default:
2885                             eFld = ww::eREF;
2886                             break;
2887                     }
2888                     sStr = FieldString(eFld);
2889                     sStr += GetExport().GetBookmarkName(nSubType,
2890                         &rRFld.GetSetRefName(), 0);
2891                     break;
2892                 case REF_FOOTNOTE:
2893                 case REF_ENDNOTE:
2894                     switch (pFld->GetFormat())
2895                     {
2896                         case REF_PAGE_PGDESC:
2897                         case REF_PAGE:
2898                             eFld = ww::ePAGEREF;
2899                             break;
2900                         case REF_UPDOWN:
2901                             eFld = ww::eREF;
2902                             break;
2903                         default:
2904                             eFld =
2905                                 REF_ENDNOTE == nSubType ? ww::eNOTEREF : ww::eFOOTREF;
2906                             break;
2907                     }
2908                     sStr = FieldString(eFld);
2909                     sStr += GetExport().GetBookmarkName(nSubType, 0,
2910                         rRFld.GetSeqNo());
2911                     break;
2912             }
2913 
2914             if (eFld != ww::eNONE)
2915             {
2916                 switch (pFld->GetFormat())
2917                 {
2918                     case REF_UPDOWN:
2919                         sStr.APPEND_CONST_ASC(" \\p");
2920                         break;
2921                     case REF_CHAPTER:
2922                         sStr.APPEND_CONST_ASC(" \\n");
2923                         break;
2924                     default:
2925                         break;
2926                 }
2927                 sStr.APPEND_CONST_ASC(" \\h ");       // insert hyperlink
2928                 GetExport().OutputField(pFld, eFld, sStr);
2929             }
2930             else
2931                 bWriteExpand = true;
2932         }
2933         break;
2934     case RES_COMBINED_CHARS:
2935         {
2936         /*
2937         We need a font size to fill in the defaults, if these are overridden
2938         (as they generally are) by character properties then those properties
2939         win.
2940 
2941         The fontsize that is used in MS for determing the defaults is always
2942         the CJK fontsize even if the text is not in that language, in OOo the
2943         largest fontsize used in the field is the one we should take, but
2944         whatever we do, word will actually render using the fontsize set for
2945         CJK text. Nevertheless we attempt to guess whether the script is in
2946         asian or western text based up on the first character and use the
2947         font size of that script as our default.
2948         */
2949         sal_uInt16 nScript;
2950         if( pBreakIt->GetBreakIter().is() )
2951             nScript = pBreakIt->GetBreakIter()->getScriptType( pFld->GetPar1(), 0);
2952         else
2953             nScript = i18n::ScriptType::ASIAN;
2954 
2955         long nHeight = ((SvxFontHeightItem&)(GetExport().GetItem(
2956             GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript)))).GetHeight();;
2957 
2958         nHeight = (nHeight + 10) / 20; //Font Size in points;
2959 
2960         /*
2961         Divide the combined char string into its up and down part. Get the
2962         font size and fill in the defaults as up == half the font size and
2963         down == a fifth the font size
2964         */
2965         xub_StrLen nAbove = (pFld->GetPar1().Len()+1)/2;
2966         sStr = FieldString(ww::eEQ);
2967         sStr.APPEND_CONST_ASC("\\o (\\s\\up ");
2968         sStr += String::CreateFromInt32(nHeight/2);
2969 
2970         sStr.Append('(');
2971         sStr += String(pFld->GetPar1(),0,nAbove);
2972         sStr.APPEND_CONST_ASC("), \\s\\do ");
2973         sStr += String::CreateFromInt32(nHeight/5);
2974 
2975         sStr.Append('(');
2976         sStr += String(pFld->GetPar1(),nAbove,pFld->GetPar1().Len()-nAbove);
2977         sStr.APPEND_CONST_ASC("))");
2978         GetExport().OutputField(pFld, ww::eEQ, sStr);
2979         }
2980         break;
2981     case RES_DROPDOWN:
2982         bWriteExpand = DropdownField( pFld );
2983         break;
2984     case RES_CHAPTERFLD:
2985         bWriteExpand = true;
2986         if (GetExport().bOutKF && rField.GetTxtFld())
2987         {
2988             const SwTxtNode *pTxtNd = GetExport().GetHdFtPageRoot();
2989             if (!pTxtNd)
2990             {
2991                 if (const SwNode *pNd = GetExport().pCurPam->GetNode())
2992                     pTxtNd = pNd->GetTxtNode();
2993             }
2994 
2995             if (pTxtNd)
2996             {
2997                 SwChapterField aCopy(*(const SwChapterField*)pFld);
2998                 aCopy.ChangeExpansion(*pTxtNd, false);
2999                 WriteExpand( &aCopy );
3000                 bWriteExpand = false;
3001             }
3002         }
3003         break;
3004         case RES_HIDDENTXTFLD:
3005         {
3006             String sExpand(pFld->GetPar2());
3007             if (sExpand.Len())
3008             {
3009                 HiddenField( *pFld );
3010             }
3011         }
3012         break;
3013         case RES_MACROFLD:
3014             sStr.ASSIGN_CONST_ASC(" MACROBUTTON");
3015             sStr += pFld->GetPar1();
3016             sStr.SearchAndReplaceAscii("StarOffice.Standard.Modul1.", String(' '));
3017             sStr += String(' ');
3018             sStr += lcl_GetExpandedField(*pFld);
3019             GetExport().OutputField( pFld, ww::eMACROBUTTON, sStr );
3020             break;
3021     default:
3022         bWriteExpand = true;
3023         break;
3024     }
3025 
3026     if (bWriteExpand)
3027         WriteExpand( pFld );
3028 }
3029 
TextFlyContent(const SwFmtFlyCnt & rFlyContent)3030 void AttributeOutputBase::TextFlyContent( const SwFmtFlyCnt& rFlyContent )
3031 {
3032     if ( GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwCntntNode ) )
3033     {
3034         SwTxtNode* pTxtNd = (SwTxtNode*)GetExport().pOutFmtNode;
3035 
3036         Point aLayPos;
3037         aLayPos = pTxtNd->FindLayoutRect( false, &aLayPos ).Pos();
3038 
3039         SwPosition aPos( *pTxtNd );
3040         sw::Frame aFrm( *rFlyContent.GetFrmFmt(), aPos );
3041 
3042         OutputFlyFrame_Impl( aFrm, aLayPos );
3043     }
3044 }
3045 
3046 // TOXMarks fehlen noch
3047 
3048 // Detaillierte Einstellungen zur Trennung erlaubt WW nur dokumentenweise.
3049 // Man koennte folgende Mimik einbauen: Die Werte des Style "Standard" werden,
3050 // falls vorhanden, in die Document Properties ( DOP ) gesetzt.
3051 // ---
3052 // ACK.  Dieser Vorschlag passt exakt zu unserer Implementierung des Import,
3053 // daher setze ich das gleich mal um. (KHZ, 07/15/2000)
ParaHyphenZone(const SvxHyphenZoneItem & rHyphenZone)3054 void WW8AttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
3055 {
3056     // sprmPFNoAutoHyph
3057     if( m_rWW8Export.bWrtWW8 )
3058         m_rWW8Export.InsUInt16( NS_sprm::LN_PFNoAutoHyph );
3059     else
3060         m_rWW8Export.pO->Insert( 44, m_rWW8Export.pO->Count() );
3061 
3062     m_rWW8Export.pO->Insert( rHyphenZone.IsHyphen() ? 0 : 1, m_rWW8Export.pO->Count() );
3063 }
3064 
ParaScriptSpace(const SfxBoolItem & rScriptSpace)3065 void WW8AttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
3066 {
3067     sal_uInt16 nId = 0;
3068     if ( m_rWW8Export.bWrtWW8 )
3069         switch ( rScriptSpace.Which() )
3070         {
3071             case RES_PARATR_SCRIPTSPACE:            nId = NS_sprm::LN_PFAutoSpaceDE;   break;
3072             case RES_PARATR_HANGINGPUNCTUATION:     nId = NS_sprm::LN_PFOverflowPunct;   break;
3073             case RES_PARATR_FORBIDDEN_RULES:        nId = NS_sprm::LN_PFKinsoku;   break;
3074         }
3075 
3076     if ( nId )
3077     {
3078         if( m_rWW8Export.bWrtWW8 )
3079             m_rWW8Export.InsUInt16( nId );
3080         else
3081             m_rWW8Export.pO->Insert( (sal_uInt8)nId, m_rWW8Export.pO->Count() );
3082 
3083         m_rWW8Export.pO->Insert( rScriptSpace.GetValue() ? 1 : 0,
3084                             m_rWW8Export.pO->Count() );
3085     }
3086 }
3087 
ParaSnapToGrid(const SvxParaGridItem & rGrid)3088 void WW8AttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
3089 {
3090     // sprmPFUsePgsuSettings
3091     // 97+ only
3092     if ( !m_rWW8Export.bWrtWW8 )
3093         return;
3094 
3095     m_rWW8Export.InsUInt16( NS_sprm::LN_PFUsePgsuSettings );
3096     m_rWW8Export.pO->Insert( rGrid.GetValue(), m_rWW8Export.pO->Count() );
3097 }
3098 
ParaVerticalAlign(const SvxParaVertAlignItem & rAlign)3099 void WW8AttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
3100 {
3101     // sprmPWAlignFont
3102     // 97+ only
3103     if( !m_rWW8Export.bWrtWW8 )
3104         return;
3105 
3106     m_rWW8Export.InsUInt16( NS_sprm::LN_PWAlignFont );
3107 
3108     sal_Int16 nVal = rAlign.GetValue();
3109     switch ( nVal )
3110     {
3111         case SvxParaVertAlignItem::BASELINE:
3112             nVal = 2;
3113             break;
3114         case SvxParaVertAlignItem::TOP:
3115             nVal = 0;
3116             break;
3117         case SvxParaVertAlignItem::CENTER:
3118             nVal = 1;
3119             break;
3120         case SvxParaVertAlignItem::BOTTOM:
3121             nVal = 3;
3122             break;
3123         case SvxParaVertAlignItem::AUTOMATIC:
3124             nVal = 4;
3125             break;
3126         default:
3127             nVal = 4;
3128             ASSERT( false, "Unknown vert alignment" );
3129             break;
3130     }
3131     m_rWW8Export.InsUInt16( nVal );
3132 }
3133 
3134 
3135 // NoHyphen: ich habe keine Entsprechung in der SW-UI und WW-UI gefunden
3136 
3137 
3138 // RefMark, NoLineBreakHere  fehlen noch
3139 
WriteFtnBegin(const SwFmtFtn & rFtn,WW8Bytes * pOutArr)3140 void WW8Export::WriteFtnBegin( const SwFmtFtn& rFtn, WW8Bytes* pOutArr )
3141 {
3142     WW8Bytes aAttrArr;
3143     bool bAutoNum = !rFtn.GetNumStr().Len();    // Auto-Nummer
3144     if( bAutoNum )
3145     {
3146         if( bWrtWW8 )
3147         {
3148             static const sal_uInt8 aSpec[] =
3149             {
3150                 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
3151                 0x55, 0x08, 1           // sprmCFSpec
3152             };
3153 
3154             aAttrArr.Insert(aSpec, sizeof(aSpec), aAttrArr.Count());
3155         }
3156         else
3157         {
3158             static sal_uInt8 const aSpec[] =
3159             {
3160                 117, 1,                         // sprmCFSpec
3161                 68, 4, 0, 0, 0, 0               // sprmCObjLocation
3162             };
3163 
3164             aAttrArr.Insert(aSpec, sizeof(aSpec), aAttrArr.Count());
3165         }
3166     }
3167 
3168     // sprmCIstd
3169     const SwEndNoteInfo* pInfo;
3170     if( rFtn.IsEndNote() )
3171         pInfo = &pDoc->GetEndNoteInfo();
3172     else
3173         pInfo = &pDoc->GetFtnInfo();
3174     const SwCharFmt* pCFmt = pOutArr
3175                                 ? pInfo->GetAnchorCharFmt( *pDoc )
3176                                 : pInfo->GetCharFmt( *pDoc );
3177     if( bWrtWW8 )
3178         SwWW8Writer::InsUInt16( aAttrArr, NS_sprm::LN_CIstd );
3179     else
3180         aAttrArr.Insert( 80, aAttrArr.Count() );
3181     SwWW8Writer::InsUInt16( aAttrArr, GetId( *pCFmt ) );
3182 
3183                                                 // fSpec-Attribut true
3184                             // Fuer Auto-Nummer muss ein Spezial-Zeichen
3185                             // in den Text und darum ein fSpec-Attribut
3186     pChpPlc->AppendFkpEntry( Strm().Tell() );
3187     if( bAutoNum )
3188         WriteChar( 0x02 );              // Auto-Nummer-Zeichen
3189     else
3190         // User-Nummerierung
3191         OutSwString( rFtn.GetNumStr(), 0, rFtn.GetNumStr().Len(),
3192                         IsUnicode(), RTL_TEXTENCODING_MS_1252 );
3193 
3194     if( pOutArr )
3195     {
3196         // insert at start of array, so the "hard" attribute overrule the
3197         // attributes of the character template
3198         pOutArr->Insert( &aAttrArr, 0 );
3199     }
3200     else
3201     {
3202         WW8Bytes aOutArr;
3203 
3204         // insert at start of array, so the "hard" attribute overrule the
3205         // attributes of the character template
3206         aOutArr.Insert( &aAttrArr, 0 );
3207 
3208         // write for the ftn number in the content, the font of the anchor
3209         const SwTxtFtn* pTxtFtn = rFtn.GetTxtFtn();
3210         if( pTxtFtn )
3211         {
3212             WW8Bytes* pOld = pO;
3213             pO = &aOutArr;
3214             SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_FONT,
3215                                                   RES_CHRATR_FONT );
3216 
3217             pCFmt = pInfo->GetCharFmt( *pDoc );
3218             aSet.Set( pCFmt->GetAttrSet() );
3219 
3220             pTxtFtn->GetTxtNode().GetAttr( aSet, *pTxtFtn->GetStart(),
3221                                             (*pTxtFtn->GetStart()) + 1 );
3222             m_pAttrOutput->OutputItem( aSet.Get( RES_CHRATR_FONT ) );
3223             pO = pOld;
3224         }
3225         pChpPlc->AppendFkpEntry( Strm().Tell(), aOutArr.Count(),
3226                                                 aOutArr.GetData() );
3227     }
3228 }
3229 
lcl_IsAtTxtEnd(const SwFmtFtn & rFtn)3230 static bool lcl_IsAtTxtEnd(const SwFmtFtn& rFtn)
3231 {
3232     bool bRet = true;
3233     if( rFtn.GetTxtFtn() )
3234     {
3235         sal_uInt16 nWh = static_cast< sal_uInt16 >(rFtn.IsEndNote() ? RES_END_AT_TXTEND
3236                                       : RES_FTN_AT_TXTEND);
3237         const SwSectionNode* pSectNd = rFtn.GetTxtFtn()->GetTxtNode().
3238                                                         FindSectionNode();
3239         while( pSectNd && FTNEND_ATPGORDOCEND ==
3240                 ((const SwFmtFtnAtTxtEnd&)pSectNd->GetSection().GetFmt()->
3241                 GetFmtAttr( nWh, true)).GetValue() )
3242             pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
3243 
3244         if (!pSectNd)
3245             bRet = false;   // the is ftn/end collected at Page- or Doc-End
3246     }
3247     return bRet;
3248 }
3249 
3250 
TextFootnote(const SwFmtFtn & rFtn)3251 void AttributeOutputBase::TextFootnote( const SwFmtFtn& rFtn )
3252 {
3253     sal_uInt16 nTyp;
3254     if ( rFtn.IsEndNote() )
3255     {
3256         nTyp = REF_ENDNOTE;
3257         if ( GetExport().bEndAtTxtEnd )
3258             GetExport().bEndAtTxtEnd = lcl_IsAtTxtEnd( rFtn );
3259     }
3260     else
3261     {
3262         nTyp = REF_FOOTNOTE;
3263         if ( GetExport().bFtnAtTxtEnd )
3264             GetExport().bFtnAtTxtEnd = lcl_IsAtTxtEnd( rFtn );
3265     }
3266 
3267     // if any reference to this footnote/endnote then insert an internal
3268     // Bookmark.
3269     String sBkmkNm;
3270     if ( GetExport().HasRefToObject( nTyp, 0, rFtn.GetTxtFtn()->GetSeqRefNo() ))
3271     {
3272         sBkmkNm = GetExport().GetBookmarkName( nTyp, 0,
3273                                     rFtn.GetTxtFtn()->GetSeqRefNo() );
3274         GetExport().AppendBookmark( sBkmkNm );
3275     }
3276 
3277     TextFootnote_Impl( rFtn );
3278 
3279     if ( sBkmkNm.Len() )
3280         GetExport().AppendBookmark( sBkmkNm ); // FIXME: Why is it added twice?  Shouldn't this one go to WW8AttributeOuput::TextFootnote_Impl()?
3281 }
3282 
TextFootnote_Impl(const SwFmtFtn & rFtn)3283 void WW8AttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFtn )
3284 {
3285     WW8_WrPlcFtnEdn* pFtnEnd;
3286     if ( rFtn.IsEndNote() )
3287         pFtnEnd = m_rWW8Export.pEdn;
3288     else
3289         pFtnEnd = m_rWW8Export.pFtn;
3290 
3291     pFtnEnd->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), rFtn );
3292     m_rWW8Export.WriteFtnBegin( rFtn, m_rWW8Export.pO );
3293 }
3294 
TextCharFormat(const SwFmtCharFmt & rCharFmt)3295 void WW8AttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
3296 {
3297     if( rCharFmt.GetCharFmt() )
3298     {
3299         if( m_rWW8Export.bWrtWW8 )
3300             m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
3301         else
3302             m_rWW8Export.pO->Insert( 80, m_rWW8Export.pO->Count() );
3303 
3304         m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *rCharFmt.GetCharFmt() ) );
3305     }
3306 }
3307 
3308 /*
3309  See ww8par6.cxx Read_DoubleLine for some more info
3310  */
CharTwoLines(const SvxTwoLinesItem & rTwoLines)3311 void WW8AttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
3312 {
3313     // #i28331# - check that bOn is set
3314     if ( rTwoLines.GetValue() )
3315     {
3316         //97+ only
3317         if( !m_rWW8Export.bWrtWW8 )
3318             return;
3319 
3320         m_rWW8Export.InsUInt16( NS_sprm::LN_CEastAsianLayout );
3321         m_rWW8Export.pO->Insert( (sal_uInt8)0x06, m_rWW8Export.pO->Count() ); //len 6
3322         m_rWW8Export.pO->Insert( (sal_uInt8)0x02, m_rWW8Export.pO->Count() );
3323 
3324         sal_Unicode cStart = rTwoLines.GetStartBracket();
3325         sal_Unicode cEnd = rTwoLines.GetEndBracket();
3326 
3327         /*
3328         As per usual we have problems. We can have seperate left and right brackets
3329         in OOo, it doesn't appear that you can in word. Also in word there appear
3330         to only be a limited number of possibilities, we can use pretty much
3331         anything.
3332 
3333         So if we have none, we export none, if either bracket is set to a known
3334         word type we export both as that type (with the bracket winning out in
3335         the case of a conflict simply being the order of test here.
3336 
3337         Upshot being a documented created in word will be reexported with no
3338         ill effects.
3339         */
3340 
3341         sal_uInt16 nType;
3342         if (!cStart && !cEnd)
3343             nType = 0;
3344         else if ((cStart == '{') || (cEnd == '}'))
3345             nType = 4;
3346         else if ((cStart == '<') || (cEnd == '>'))
3347             nType = 3;
3348         else if ((cStart == '[') || (cEnd == ']'))
3349             nType = 2;
3350         else
3351             nType = 1;
3352         m_rWW8Export.InsUInt16( nType );
3353         static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 };
3354         m_rWW8Export.pO->Insert( aZeroArr, 3, m_rWW8Export.pO->Count() );
3355     }
3356 }
3357 
ParaNumRule(const SwNumRuleItem & rNumRule)3358 void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule )
3359 {
3360     const SwTxtNode* pTxtNd = 0;
3361     sal_uInt16 nNumId;
3362     sal_uInt8 nLvl = 0;
3363     if ( rNumRule.GetValue().Len() )
3364     {
3365         const SwNumRule* pRule = GetExport().pDoc->FindNumRulePtr(
3366                                         rNumRule.GetValue() );
3367         if ( pRule && USHRT_MAX != ( nNumId = GetExport().GetId( *pRule ) ) )
3368         {
3369             ++nNumId;
3370             if ( GetExport().pOutFmtNode )
3371             {
3372                 if ( GetExport().pOutFmtNode->ISA( SwCntntNode ) )
3373                 {
3374                     pTxtNd = (SwTxtNode*)GetExport().pOutFmtNode;
3375 
3376                     if( pTxtNd->IsCountedInList())
3377                     {
3378                         nLvl = static_cast< sal_uInt8 >(pTxtNd->GetActualListLevel());
3379 
3380                         if ( pTxtNd->IsListRestart() )
3381                         {
3382                             sal_uInt16 nStartWith = static_cast< sal_uInt16 >( pTxtNd->GetActualListStartValue() );
3383                             nNumId = GetExport().DuplicateNumRule( pRule, nLvl, nStartWith );
3384                             if ( USHRT_MAX != nNumId )
3385                                 ++nNumId;
3386                         }
3387                     }
3388                     else
3389                     {
3390                         // #i44815# adjust numbering for numbered paragraphs
3391                         // without number (NO_NUMLEVEL). These paragaphs
3392                         // will receive a list id 0, which WW interprets as
3393                         // 'no number'.
3394                         nNumId = 0;
3395                     }
3396                 }
3397                 else if ( GetExport().pOutFmtNode->ISA( SwTxtFmtColl ) )
3398                 {
3399                     const SwTxtFmtColl* pC = (SwTxtFmtColl*)GetExport().pOutFmtNode;
3400                     if ( pC && pC->IsAssignedToListLevelOfOutlineStyle() )
3401                         nLvl = static_cast< sal_uInt8 >( pC->GetAssignedOutlineStyleLevel() ); //<-end,zhaojianwei
3402                 }
3403             }
3404         }
3405         else
3406             nNumId = USHRT_MAX;
3407     }
3408     else
3409         nNumId = 0;
3410 
3411     if ( USHRT_MAX != nNumId )
3412     {
3413         if ( nLvl >= WW8ListManager::nMaxLevel )
3414             nLvl = WW8ListManager::nMaxLevel - 1;
3415 
3416         ParaNumRule_Impl( pTxtNd, nLvl, nNumId );
3417     }
3418 }
3419 
ParaNumRule_Impl(const SwTxtNode * pTxtNd,sal_Int32 nLvl,sal_Int32 nNumId)3420 void WW8AttributeOutput::ParaNumRule_Impl( const SwTxtNode* pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId )
3421 {
3422     if ( m_rWW8Export.bWrtWW8 )
3423     {
3424         // write sprmPIlvl and sprmPIlfo
3425         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlvl );
3426 		m_rWW8Export.pO->Insert( ::sal::static_int_cast<sal_uInt8>(nLvl), m_rWW8Export.pO->Count() );
3427         SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlfo );
3428 		SwWW8Writer::InsUInt16( *m_rWW8Export.pO, ::sal::static_int_cast<sal_uInt16>(nNumId) );
3429     }
3430     else if ( pTxtNd && m_rWW8Export.Out_SwNum( pTxtNd ) )                // NumRules
3431         m_rWW8Export.pSepx->SetNum( pTxtNd );
3432 }
3433 
3434 /* File FRMATR.HXX */
3435 
FormatFrameSize(const SwFmtFrmSize & rSize)3436 void WW8AttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
3437 {
3438     if( m_rWW8Export.bOutFlyFrmAttrs )                   // Flys
3439     {
3440         if( m_rWW8Export.bOutGrf )
3441             return;                // Fly um Grafik -> Auto-Groesse
3442 
3443 //???? was ist bei Prozentangaben ???
3444         if ( rSize.GetWidth() && rSize.GetWidthSizeType() == ATT_FIX_SIZE)
3445         {
3446             //"sprmPDxaWidth"
3447             if( m_rWW8Export.bWrtWW8 )
3448                 m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaWidth );
3449             else
3450                 m_rWW8Export.pO->Insert( 28, m_rWW8Export.pO->Count() );
3451             m_rWW8Export.InsUInt16( (sal_uInt16)rSize.GetWidth() );
3452         }
3453 
3454         if ( rSize.GetHeight() )
3455         {
3456             // sprmPWHeightAbs
3457             if( m_rWW8Export.bWrtWW8 )
3458                 m_rWW8Export.InsUInt16( NS_sprm::LN_PWHeightAbs );
3459             else
3460                 m_rWW8Export.pO->Insert( 45, m_rWW8Export.pO->Count() );
3461 
3462             sal_uInt16 nH = 0;
3463             switch ( rSize.GetHeightSizeType() )
3464             {
3465                 case ATT_VAR_SIZE: break;
3466                 case ATT_FIX_SIZE: nH = (sal_uInt16)rSize.GetHeight() & 0x7fff; break;
3467                 default:           nH = (sal_uInt16)rSize.GetHeight() | 0x8000; break;
3468             }
3469             m_rWW8Export.InsUInt16( nH );
3470         }
3471     }
3472     else if( m_rWW8Export.bOutPageDescs )            // PageDesc : Breite + Hoehe
3473     {
3474         if( m_rWW8Export.pAktPageDesc->GetLandscape() )
3475         {
3476             /*sprmSBOrientation*/
3477             if( m_rWW8Export.bWrtWW8 )
3478                 m_rWW8Export.InsUInt16( NS_sprm::LN_SBOrientation );
3479             else
3480                 m_rWW8Export.pO->Insert( 162, m_rWW8Export.pO->Count() );
3481             m_rWW8Export.pO->Insert( 2, m_rWW8Export.pO->Count() );
3482         }
3483 
3484         /*sprmSXaPage*/
3485         if( m_rWW8Export.bWrtWW8 )
3486             m_rWW8Export.InsUInt16( NS_sprm::LN_SXaPage );
3487         else
3488             m_rWW8Export.pO->Insert( 164, m_rWW8Export.pO->Count() );
3489         m_rWW8Export.InsUInt16(
3490             msword_cast<sal_uInt16>(SvxPaperInfo::GetSloppyPaperDimension(rSize.GetWidth())));
3491 
3492         /*sprmSYaPage*/
3493         if( m_rWW8Export.bWrtWW8 )
3494             m_rWW8Export.InsUInt16( NS_sprm::LN_SYaPage );
3495         else
3496             m_rWW8Export.pO->Insert( 165, m_rWW8Export.pO->Count() );
3497         m_rWW8Export.InsUInt16(
3498             msword_cast<sal_uInt16>(SvxPaperInfo::GetSloppyPaperDimension(rSize.GetHeight())));
3499     }
3500 }
3501 
3502 // FillOrder fehlt noch
3503 
3504 // ReplaceCr() wird fuer Pagebreaks und Pagedescs gebraucht. Es wird ein
3505 // bereits geschriebenes CR durch ein Break-Zeichen ersetzt. Replace muss
3506 // direkt nach Schreiben des CR gerufen werden.
3507 // Rueckgabe: FilePos des ersetzten CRs + 1 oder 0 fuer nicht ersetzt
3508 
ReplaceCr(sal_uInt8 nChar)3509 sal_uLong WW8Export::ReplaceCr( sal_uInt8 nChar )
3510 {
3511     // Bug #49917#
3512     ASSERT( nChar, "gegen 0 ersetzt bringt WW97/95 zum Absturz" );
3513 
3514     bool bReplaced = false;
3515     SvStream& rStrm = Strm();
3516     sal_uLong nRetPos = 0, nPos = rStrm.Tell();
3517     sal_uInt8 nBCode=0;
3518     sal_uInt16 nUCode=0;
3519     //If there is at least two characters already output
3520     if (nPos - (IsUnicode() ? 2 : 1) >= sal_uLong(pFib->fcMin))
3521     {
3522         rStrm.SeekRel(IsUnicode() ? -2 : -1);
3523         if (IsUnicode())
3524             rStrm >> nUCode;
3525         else
3526         {
3527             rStrm >> nBCode;
3528             nUCode = nBCode;
3529         }
3530         //If the last char was a cr
3531         if (nUCode == 0x0d)             // CR ?
3532         {
3533             if ((nChar == 0x0c) &&
3534                 (nPos - (IsUnicode() ? 4 : 2) >= sal_uLong(pFib->fcMin)))
3535             {
3536                 rStrm.SeekRel( IsUnicode() ? -4 : -2 );
3537                 if (IsUnicode())
3538                     rStrm >> nUCode;
3539                 else
3540                 {
3541                     rStrm >> nUCode;
3542                     nUCode = nBCode;
3543                 }
3544             }
3545             else
3546             {
3547                 rStrm.SeekRel( IsUnicode() ? -2 : -1 );
3548                 nUCode = 0x0;
3549             }
3550             //And the para is not of len 0, then replace this cr with the mark
3551 			//#120140# If there is a cr before a column break, need replace the cr. So remove the "nChar==0x0e" check.
3552             if( nUCode == 0x0d )
3553                 bReplaced = false;
3554             else
3555             {
3556                 bReplaced = true;
3557                 WriteChar(nChar);
3558                 nRetPos = nPos;
3559             }
3560         }
3561         else if ((nUCode == 0x0c) && (nChar == 0x0e))
3562         {
3563             //#108854# a column break after a section has
3564             //no effect in writer
3565             bReplaced = true;
3566         }
3567         rStrm.Seek( nPos );
3568     }
3569     else
3570         bReplaced = true;
3571 
3572     if (!bReplaced)
3573     {
3574         // then write as normal char
3575         WriteChar(nChar);
3576         pPiece->SetParaBreak();
3577         pPapPlc->AppendFkpEntry(rStrm.Tell());
3578         pChpPlc->AppendFkpEntry(rStrm.Tell());
3579         nRetPos = rStrm.Tell();
3580     }
3581 #ifndef DBG_UTIL
3582     else
3583     {
3584         ASSERT( nRetPos || nPos == (sal_uLong)pFib->fcMin,
3585                 "WW8_ReplaceCr an falscher FilePos gerufen" );
3586     }
3587 #endif
3588     return nRetPos;
3589 }
3590 
TableRowEnd(sal_uInt32 nDepth)3591 void WW8AttributeOutput::TableRowEnd(sal_uInt32 nDepth)
3592 {
3593     if ( nDepth == 1 )
3594         m_rWW8Export.WriteChar( (sal_uInt8)0x07 );
3595     else if ( nDepth > 1 )
3596         m_rWW8Export.WriteChar( (sal_uInt8)0x0d );
3597 
3598     //Technically in a word document this is a different value for a row ends
3599     //that are not row ends directly after a cell with a graphic. But it
3600     //doesn't seem to make a difference
3601     //pMagicTable->Append(Fc2Cp(Strm().Tell()),0x1B6);
3602 }
3603 
FormatPageDescription(const SwFmtPageDesc & rPageDesc)3604 void AttributeOutputBase::FormatPageDescription( const SwFmtPageDesc& rPageDesc )
3605 {
3606     if ( GetExport().bStyDef && GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwTxtFmtColl ) )
3607     {
3608         const SwTxtFmtColl* pC = (SwTxtFmtColl*)GetExport().pOutFmtNode;
3609         if ( (SFX_ITEM_SET != pC->GetItemState( RES_BREAK, false ) ) && rPageDesc.KnowsPageDesc() )
3610             FormatBreak( SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK ) );
3611     }
3612 }
3613 
PageBreakBefore(bool bBreak)3614 void WW8AttributeOutput::PageBreakBefore( bool bBreak )
3615 {
3616     // sprmPPageBreakBefore/sprmPFPageBreakBefore
3617     if ( m_rWW8Export.bWrtWW8 )
3618         m_rWW8Export.InsUInt16( NS_sprm::LN_PFPageBreakBefore );
3619     else
3620         m_rWW8Export.pO->Insert( 9, m_rWW8Export.pO->Count() );
3621 
3622     m_rWW8Export.pO->Insert( bBreak ? 1 : 0, m_rWW8Export.pO->Count() );
3623 }
3624 
3625 // Breaks schreiben nichts in das Ausgabe-Feld rWrt.pO,
3626 // sondern nur in den Text-Stream ( Bedingung dafuer, dass sie von Out_Break...
3627 // gerufen werden duerfen )
FormatBreak(const SvxFmtBreakItem & rBreak)3628 void AttributeOutputBase::FormatBreak( const SvxFmtBreakItem& rBreak )
3629 {
3630     if ( GetExport().bStyDef )
3631     {
3632         switch ( rBreak.GetBreak() )
3633         {
3634             // JP 21.06.99: column breaks never change to pagebreaks
3635             // case SVX_BREAK_COLUMN_BEFORE:
3636             // case SVX_BREAK_COLUMN_BOTH:
3637             case SVX_BREAK_NONE:
3638             case SVX_BREAK_PAGE_BEFORE:
3639             case SVX_BREAK_PAGE_BOTH:
3640                 PageBreakBefore( rBreak.GetValue() );
3641                 break;
3642             default:
3643                 break;
3644         }
3645     }
3646     else if ( !GetExport().mpParentFrame )
3647     {
3648         sal_uInt8 nC = 0;
3649         bool bBefore = false;
3650         // --> OD 2007-05-29 #i76300#
3651         // Note: Can only be <true>, if <bBefore> equals <false>.
3652         bool bCheckForFollowPageDesc = false;
3653         // <--
3654 
3655         switch ( rBreak.GetBreak() )
3656         {
3657             case SVX_BREAK_NONE:                                // Ausgeschaltet
3658                 if ( !GetExport().bBreakBefore )
3659                     PageBreakBefore( false );
3660                 return;
3661 
3662             case SVX_BREAK_COLUMN_BEFORE:                       // ColumnBreak
3663                 bBefore = true;
3664                 // no break;
3665             case SVX_BREAK_COLUMN_AFTER:
3666             case SVX_BREAK_COLUMN_BOTH:
3667                 if ( GetExport().Sections().CurrentNumberOfColumns( *GetExport().pDoc ) > 1 )
3668                 {
3669                     nC = msword::ColumnBreak;
3670                 }
3671                 break;
3672 
3673             case SVX_BREAK_PAGE_BEFORE:                         // PageBreak
3674                 // From now on(fix for #i77900#) we prefer to save a page break as
3675                 // paragraph attribute, this has to be done after the export of the
3676                 // paragraph ( => !GetExport().bBreakBefore )
3677                 if ( !GetExport().bBreakBefore )
3678                     PageBreakBefore( true );
3679                 break;
3680 
3681             case SVX_BREAK_PAGE_AFTER:
3682             case SVX_BREAK_PAGE_BOTH:
3683                 nC = msword::PageBreak;
3684                 // --> OD 2007-05-29 #i76300#
3685                 // check for follow page description, if current writing attributes
3686                 // of a paragraph.
3687                 if ( dynamic_cast< const SwTxtNode* >( GetExport().pOutFmtNode ) &&
3688                      GetExport().GetCurItemSet() )
3689                 {
3690                     bCheckForFollowPageDesc = true;
3691                 }
3692                 // <--
3693                 break;
3694 
3695             default:
3696                 break;
3697         }
3698 
3699         if ( ( bBefore == GetExport().bBreakBefore ) && nC )  // #49917#
3700         {
3701             // --> OD 2007-05-29 #i76300#
3702             bool bFollowPageDescWritten = false;
3703             if ( bCheckForFollowPageDesc && !bBefore )
3704             {
3705                 bFollowPageDescWritten =
3706                     GetExport().OutputFollowPageDesc( GetExport().GetCurItemSet(),
3707                             dynamic_cast<const SwTxtNode*>( GetExport().pOutFmtNode ) );
3708             }
3709             if ( !bFollowPageDescWritten )
3710             {
3711                 SectionBreak( nC );
3712             }
3713             // <--
3714         }
3715     }
3716 }
3717 
SectionBreak(sal_uInt8 nC,const WW8_SepInfo *)3718 void WW8AttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* /*pSectionInfo*/ )
3719 {
3720     m_rWW8Export.ReplaceCr( nC );
3721 }
3722 
FormatTextGrid(const SwTextGridItem & rGrid)3723 void WW8AttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid )
3724 {
3725     if ( m_rWW8Export.bOutPageDescs && m_rWW8Export.bWrtWW8 )
3726     {
3727         sal_uInt16 nGridType = 0;
3728         switch ( rGrid.GetGridType() )
3729         {
3730             default:
3731                 ASSERT(false, "Unknown grid type");
3732             case GRID_NONE:
3733                 nGridType = 0;
3734                 break;
3735             case GRID_LINES_ONLY:
3736                 nGridType = 2;
3737                 break;
3738             case GRID_LINES_CHARS:
3739                 if ( rGrid.IsSnapToChars() )
3740                     nGridType = 3;
3741                 else
3742                     nGridType = 1;
3743                 break;
3744         }
3745         m_rWW8Export.InsUInt16( NS_sprm::LN_SClm );
3746         m_rWW8Export.InsUInt16( nGridType );
3747 
3748         sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
3749         m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaLinePitch );
3750         m_rWW8Export.InsUInt16( nHeight );
3751 
3752         MSWordStyles * pStyles = m_rWW8Export.pStyles;
3753         SwFmt * pSwFmt = pStyles->GetSwFmt();
3754 
3755         sal_uInt32 nPageCharSize = 0;
3756 
3757         if (pSwFmt != NULL)
3758         {
3759             nPageCharSize = ItemGet<SvxFontHeightItem>
3760             (*pSwFmt, RES_CHRATR_CJK_FONTSIZE).GetHeight();
3761         }
3762 
3763         sal_Int32 nCharWidth = rGrid.GetBaseWidth() - nPageCharSize;
3764         sal_Int32 nFraction = 0;
3765         nFraction = nCharWidth % 20;
3766         if ( nCharWidth < 0 )
3767             nFraction = 20 + nFraction;
3768         nFraction = ( nFraction * 0xFFF ) / 20;
3769         nFraction = ( nFraction & 0x00000FFF );
3770 
3771         sal_Int32 nMain = 0;
3772         nMain = nCharWidth / 20;
3773         if ( nCharWidth < 0 )
3774             nMain -= 1;
3775         nMain = nMain * 0x1000;
3776         nMain = ( nMain & 0xFFFFF000 );
3777 
3778         sal_uInt32 nCharSpace = nFraction + nMain;
3779         m_rWW8Export.InsUInt16( NS_sprm::LN_SDxtCharSpace );
3780         m_rWW8Export.InsUInt32( nCharSpace );
3781     }
3782 }
3783 
FormatPaperBin(const SvxPaperBinItem & rPaperBin)3784 void WW8AttributeOutput::FormatPaperBin( const SvxPaperBinItem& rPaperBin )
3785 {
3786     if ( m_rWW8Export.bOutPageDescs )
3787     {
3788         sal_uInt16 nVal;
3789         switch ( rPaperBin.GetValue() )
3790         {
3791             case 0: nVal = 15;  break;      // Automatically select
3792             case 1: nVal = 1;   break;      // Upper paper tray
3793             case 2: nVal = 4;   break;      // Manual paper feed
3794             default: nVal = 0;  break;
3795         }
3796 
3797         if ( nVal )
3798         {
3799             if( m_rWW8Export.bWrtWW8 )
3800                 m_rWW8Export.InsUInt16( m_rWW8Export.bOutFirstPage? NS_sprm::LN_SDmBinFirst: NS_sprm::LN_SDmBinOther );
3801             else
3802                 m_rWW8Export.pO->Insert( m_rWW8Export.bOutFirstPage? 140: 141, m_rWW8Export.pO->Count() );
3803 
3804             m_rWW8Export.InsUInt16( nVal );
3805         }
3806     }
3807 }
3808 
FormatLRSpace(const SvxLRSpaceItem & rLR)3809 void WW8AttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLR )
3810 {
3811     // Flys fehlen noch ( siehe RTF )
3812 
3813     if ( m_rWW8Export.bOutFlyFrmAttrs )                   // Flys
3814     {
3815         // sprmPDxaFromText10
3816         if( m_rWW8Export.bWrtWW8 )
3817             m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText10 );
3818         else
3819             m_rWW8Export.pO->Insert( 49, m_rWW8Export.pO->Count() );
3820         // Mittelwert nehmen, da WW nur 1 Wert kennt
3821         m_rWW8Export.InsUInt16( (sal_uInt16) ( ( rLR.GetLeft() + rLR.GetRight() ) / 2 ) );
3822     }
3823     else if ( m_rWW8Export.bOutPageDescs )                // PageDescs
3824     {
3825         sal_uInt16 nLDist, nRDist;
3826         const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_BOX );
3827         if ( pItem )
3828         {
3829             nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
3830             nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
3831         }
3832         else
3833             nLDist = nRDist = 0;
3834         nLDist = nLDist + (sal_uInt16)rLR.GetLeft();
3835         nRDist = nRDist + (sal_uInt16)rLR.GetRight();
3836 
3837         // sprmSDxaLeft
3838         if( m_rWW8Export.bWrtWW8 )
3839             m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaLeft );
3840         else
3841             m_rWW8Export.pO->Insert( 166, m_rWW8Export.pO->Count() );
3842         m_rWW8Export.InsUInt16( nLDist );
3843 
3844         // sprmSDxaRight
3845         if( m_rWW8Export.bWrtWW8 )
3846             m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaRight );
3847         else
3848             m_rWW8Export.pO->Insert( 167, m_rWW8Export.pO->Count() );
3849         m_rWW8Export.InsUInt16( nRDist );
3850     }
3851     else
3852     {                                          // normale Absaetze
3853         // sprmPDxaLeft
3854         if( m_rWW8Export.bWrtWW8 )
3855         {
3856             m_rWW8Export.InsUInt16( 0x845E );        //asian version ?
3857             m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetTxtLeft() );
3858         }
3859         else
3860         {
3861             m_rWW8Export.pO->Insert( 17, m_rWW8Export.pO->Count() );
3862             m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetTxtLeft() );
3863         }
3864 
3865         // sprmPDxaRight
3866         if( m_rWW8Export.bWrtWW8 )
3867         {
3868             m_rWW8Export.InsUInt16( 0x845D );        //asian version ?
3869             m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetRight() );
3870         }
3871         else
3872         {
3873             m_rWW8Export.pO->Insert( 16, m_rWW8Export.pO->Count() );
3874             m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetRight() );
3875         }
3876 
3877         // sprmPDxaLeft1
3878         if( m_rWW8Export.bWrtWW8 )
3879         {
3880             m_rWW8Export.InsUInt16( 0x8460 );        //asian version ?
3881             m_rWW8Export.InsUInt16( rLR.GetTxtFirstLineOfst() );
3882         }
3883         else
3884         {
3885             m_rWW8Export.pO->Insert( 19, m_rWW8Export.pO->Count() );
3886             m_rWW8Export.InsUInt16( rLR.GetTxtFirstLineOfst() );
3887         }
3888     }
3889 }
3890 
FormatULSpace(const SvxULSpaceItem & rUL)3891 void WW8AttributeOutput::FormatULSpace( const SvxULSpaceItem& rUL )
3892 {
3893     // Flys fehlen noch ( siehe RTF )
3894 
3895     if ( m_rWW8Export.bOutFlyFrmAttrs )                   // Flys
3896     {
3897         // sprmPDyaFromText
3898         if( m_rWW8Export.bWrtWW8 )
3899             m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaFromText );
3900         else
3901             m_rWW8Export.pO->Insert( 48, m_rWW8Export.pO->Count() );
3902         // Mittelwert nehmen, da WW nur 1 Wert kennt
3903         m_rWW8Export.InsUInt16( (sal_uInt16) ( ( rUL.GetUpper() + rUL.GetLower() ) / 2 ) );
3904     }
3905     else if ( m_rWW8Export.bOutPageDescs )            // Page-UL
3906     {
3907         ASSERT( m_rWW8Export.GetCurItemSet(), "Impossible" );
3908         if ( !m_rWW8Export.GetCurItemSet() )
3909             return;
3910 
3911         HdFtDistanceGlue aDistances( *m_rWW8Export.GetCurItemSet() );
3912 
3913         if ( aDistances.HasHeader() )
3914         {
3915             //sprmSDyaHdrTop
3916             if ( m_rWW8Export.bWrtWW8 )
3917                 m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaHdrTop );
3918             else
3919                 m_rWW8Export.pO->Insert( 156, m_rWW8Export.pO->Count() );
3920             m_rWW8Export.InsUInt16( aDistances.dyaHdrTop );
3921         }
3922 
3923         // sprmSDyaTop
3924         if ( m_rWW8Export.bWrtWW8 )
3925             m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaTop );
3926         else
3927             m_rWW8Export.pO->Insert( 168, m_rWW8Export.pO->Count() );
3928         m_rWW8Export.InsUInt16( aDistances.dyaTop );
3929 
3930         if ( aDistances.HasFooter() )
3931         {
3932             //sprmSDyaHdrBottom
3933             if ( m_rWW8Export.bWrtWW8 )
3934                 m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaHdrBottom );
3935             else
3936                 m_rWW8Export.pO->Insert( 157, m_rWW8Export.pO->Count() );
3937             m_rWW8Export.InsUInt16( aDistances.dyaHdrBottom );
3938         }
3939 
3940         //sprmSDyaBottom
3941         if ( m_rWW8Export.bWrtWW8 )
3942             m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaBottom );
3943         else
3944             m_rWW8Export.pO->Insert( 169, m_rWW8Export.pO->Count() );
3945         m_rWW8Export.InsUInt16( aDistances.dyaBottom );
3946     }
3947     else
3948     {
3949         // sprmPDyaBefore
3950         if ( m_rWW8Export.bWrtWW8 )
3951             m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaBefore );
3952         else
3953             m_rWW8Export.pO->Insert( 21, m_rWW8Export.pO->Count() );
3954         m_rWW8Export.InsUInt16( rUL.GetUpper() );
3955         // sprmPDyaAfter
3956         if( m_rWW8Export.bWrtWW8 )
3957             m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaAfter );
3958         else
3959             m_rWW8Export.pO->Insert( 22, m_rWW8Export.pO->Count() );
3960         m_rWW8Export.InsUInt16( rUL.GetLower() );
3961     }
3962 }
3963 
3964 // Print, Opaque, Protect fehlen noch
3965 
FormatSurround(const SwFmtSurround & rSurround)3966 void WW8AttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
3967 {
3968     if ( m_rWW8Export.bOutFlyFrmAttrs )
3969     {
3970         if ( m_rWW8Export.bWrtWW8 )
3971             m_rWW8Export.InsUInt16( NS_sprm::LN_PWr );
3972         else
3973             m_rWW8Export.pO->Insert( 37, m_rWW8Export.pO->Count() );
3974 
3975         m_rWW8Export.pO->Insert(
3976                 ( SURROUND_NONE != rSurround.GetSurround() ) ? 2 : 1,
3977                 m_rWW8Export.pO->Count() );
3978     }
3979 }
3980 
FormatVertOrientation(const SwFmtVertOrient & rFlyVert)3981 void WW8AttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
3982 {
3983 //!!!! Ankertyp und entsprechende Umrechnung fehlt noch
3984 
3985     if ( m_rWW8Export.bOutFlyFrmAttrs )
3986     {
3987         short nPos;
3988         switch( rFlyVert.GetVertOrient() )
3989         {
3990             case text::VertOrientation::NONE:
3991                 nPos = (short)rFlyVert.GetPos();
3992                 break;
3993             case text::VertOrientation::CENTER:
3994             case text::VertOrientation::LINE_CENTER:
3995                 nPos = -8;
3996                 break;
3997             case text::VertOrientation::BOTTOM:
3998             case text::VertOrientation::LINE_BOTTOM:
3999                 nPos = -12;
4000                 break;
4001             case text::VertOrientation::TOP:
4002             case text::VertOrientation::LINE_TOP:
4003             default:
4004                 nPos = -4;
4005                 break;
4006         }
4007 
4008         // sprmPDyaAbs
4009         if ( m_rWW8Export.bWrtWW8 )
4010             m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaAbs );
4011         else
4012             m_rWW8Export.pO->Insert( 27, m_rWW8Export.pO->Count() );
4013         m_rWW8Export.InsUInt16( nPos );
4014     }
4015 }
4016 
4017 
FormatHorizOrientation(const SwFmtHoriOrient & rFlyHori)4018 void WW8AttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
4019 {
4020     if ( !m_rWW8Export.mpParentFrame )
4021     {
4022         ASSERT( m_rWW8Export.mpParentFrame, "HoriOrient without mpParentFrame !!" );
4023         return;
4024     }
4025 
4026 //!!!! Ankertyp und entsprechende Umrechnung fehlt noch
4027     if ( m_rWW8Export.bOutFlyFrmAttrs )
4028     {
4029         short nPos;
4030         switch( rFlyHori.GetHoriOrient() )
4031         {
4032             case text::HoriOrientation::NONE:
4033                 nPos = (short)rFlyHori.GetPos();
4034                 if( !nPos )
4035                     nPos = 1;   // WW: 0 ist reserviert
4036                 break;
4037             case text::HoriOrientation::LEFT:
4038                 nPos = rFlyHori.IsPosToggle() ? -12 : 0;
4039                 break;
4040             case text::HoriOrientation::RIGHT:
4041                 nPos = rFlyHori.IsPosToggle() ? -16 : -8;
4042                 break;
4043             case text::HoriOrientation::CENTER:
4044             case text::HoriOrientation::FULL:                         // FULL nur fuer Tabellen
4045             default:
4046                 nPos = -4;
4047                 break;
4048         }
4049 
4050         // sprmPDxaAbs
4051         if( m_rWW8Export.bWrtWW8 )
4052             m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaAbs );
4053         else
4054             m_rWW8Export.pO->Insert( 26, m_rWW8Export.pO->Count() );
4055         m_rWW8Export.InsUInt16( nPos );
4056     }
4057 }
4058 
FormatAnchor(const SwFmtAnchor & rAnchor)4059 void WW8AttributeOutput::FormatAnchor( const SwFmtAnchor& rAnchor )
4060 {
4061     ASSERT( m_rWW8Export.mpParentFrame, "Anchor without mpParentFrame !!" );
4062 
4063     if ( m_rWW8Export.bOutFlyFrmAttrs )
4064     {
4065         sal_uInt8 nP = 0;
4066         switch ( rAnchor.GetAnchorId() )
4067         {
4068             case FLY_AT_PAGE:
4069                 // Vert: Page | Horz: Page
4070                 nP |= (1 << 4) | (2 << 6);
4071                 break;
4072             // Im Fall eine Flys als Zeichen: Absatz-gebunden setzen!!!
4073             case FLY_AT_FLY:
4074             case FLY_AT_CHAR:
4075             case FLY_AT_PARA:
4076             case FLY_AS_CHAR:
4077                 // Vert: Page | Horz: Page
4078                 nP |= (2 << 4) | (0 << 6);
4079                 break;
4080             default:
4081                 break;
4082         }
4083 
4084         // sprmPPc
4085         if ( m_rWW8Export.bWrtWW8 )
4086             m_rWW8Export.InsUInt16( NS_sprm::LN_PPc );
4087         else
4088             m_rWW8Export.pO->Insert( 29, m_rWW8Export.pO->Count() );
4089         m_rWW8Export.pO->Insert( nP, m_rWW8Export.pO->Count() );
4090     }
4091 }
4092 
FormatBackground(const SvxBrushItem & rBrush)4093 void WW8AttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
4094 {
4095     // WW cannot have background in a section
4096     if ( !m_rWW8Export.bOutPageDescs )
4097     {
4098         WW8_SHD aSHD;
4099 
4100         m_rWW8Export.TransBrush( rBrush.GetColor(), aSHD );
4101         // sprmPShd
4102         if ( m_rWW8Export.bWrtWW8 )
4103             m_rWW8Export.InsUInt16( NS_sprm::LN_PShd );
4104         else
4105             m_rWW8Export.pO->Insert(47, m_rWW8Export.pO->Count());
4106         m_rWW8Export.InsUInt16( aSHD.GetValue() );
4107 
4108         // Quite a few unknowns, some might be transparency or something
4109         // of that nature...
4110         if ( m_rWW8Export.bWrtWW8 )
4111         {
4112             m_rWW8Export.InsUInt16( 0xC64D );
4113             m_rWW8Export.pO->Insert( 10, m_rWW8Export.pO->Count() );
4114             m_rWW8Export.InsUInt32( 0xFF000000 );
4115             m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor().GetColor() ) );
4116             m_rWW8Export.InsUInt16( 0x0000 );
4117         }
4118     }
4119 }
4120 
TranslateBorderLine(const SvxBorderLine & rLine,sal_uInt16 nDist,bool bShadow)4121 WW8_BRC WW8Export::TranslateBorderLine(const SvxBorderLine& rLine,
4122     sal_uInt16 nDist, bool bShadow)
4123 {
4124     // M.M. This function writes out border lines to the word format similar to
4125     // what SwRTFWriter::OutRTFBorder does in the RTF filter Eventually it
4126     // would be nice if all this functionality was in the one place
4127     WW8_BRC aBrc;
4128     sal_uInt16 nWidth = rLine.GetInWidth() + rLine.GetOutWidth();
4129     sal_uInt8 brcType = 0, nColCode = 0;
4130 
4131     if( nWidth )                                // Linie ?
4132     {
4133         // BRC.brcType
4134         bool bDouble = 0 != rLine.GetInWidth() && 0 != rLine.GetOutWidth();
4135         bool bThick = !bDouble && !bWrtWW8 && nWidth > 75;
4136         if( bDouble )
4137             brcType = 3;
4138         else if( bThick )
4139             brcType = 2;
4140         else
4141             brcType = 1;
4142 
4143         // BRC.dxpLineWidth
4144         if( bThick )
4145             nWidth /= 2;
4146 
4147         if( bWrtWW8 )
4148         {
4149             // Angabe in 8tel Punkten, also durch 2.5, da 1 Punkt = 20 Twips
4150             nWidth = (( nWidth * 8 ) + 10 ) / 20;
4151             if( 0xff < nWidth )
4152                 nWidth = 0xff;
4153         }
4154         else
4155         {
4156             // Angabe in 0.75 pt
4157             nWidth = ( nWidth + 7 ) / 15;
4158             if( nWidth > 5 )
4159                 nWidth = 5;
4160         }
4161 
4162         if( 0 == nWidth )                       // ganz duenne Linie
4163             nWidth = 1;                         //       nicht weglassen
4164 
4165         // BRC.ico
4166         nColCode = TransCol( rLine.GetColor() );
4167     }
4168 
4169     // BRC.dxpSpace
4170     sal_uInt16 nLDist = nDist;
4171     nLDist /= 20;               // Masseinheit : pt
4172     if( nLDist > 0x1f )
4173         nLDist = 0x1f;
4174 
4175     if( bWrtWW8 )
4176     {
4177         aBrc.aBits1[0] = sal_uInt8(nWidth);
4178         aBrc.aBits1[1] = brcType;
4179         aBrc.aBits2[0] = nColCode;
4180         aBrc.aBits2[1] = sal_uInt8(nLDist);
4181 
4182         // fShadow, keine weiteren Einstellungen im WW moeglich
4183         if( bShadow )
4184             aBrc.aBits2[1] |= 0x20;
4185     }
4186     else
4187     {
4188         sal_uInt16 aBits = nWidth + ( brcType << 3 );
4189         aBits |= (nColCode & 0x1f) << 6;
4190         aBits |= nLDist << 11;
4191         // fShadow, keine weiteren Einstellungen im WW moeglich
4192         if( bShadow )
4193             aBits |= 0x20;
4194         ShortToSVBT16( aBits, aBrc.aBits1);
4195     }
4196 
4197     return aBrc;
4198 }
4199 
4200 // MakeBorderLine() bekommt einen WW8Bytes* uebergeben, um die Funktion
4201 // auch fuer die Tabellen-Umrandungen zu benutzen.
4202 // Wenn nSprmNo == 0, dann wird der Opcode nicht ausgegeben.
4203 // bShadow darf bei Tabellenzellen *nicht* gesetzt sein !
Out_BorderLine(WW8Bytes & rO,const SvxBorderLine * pLine,sal_uInt16 nDist,sal_uInt16 nSprmNo,bool bShadow)4204 void WW8Export::Out_BorderLine(WW8Bytes& rO, const SvxBorderLine* pLine,
4205     sal_uInt16 nDist, sal_uInt16 nSprmNo, bool bShadow)
4206 {
4207     ASSERT( ( nSprmNo == 0 ) ||
4208             ( nSprmNo >= 38 && nSprmNo <= 41 ) ||
4209             ( nSprmNo >= NS_sprm::LN_PBrcTop && nSprmNo <= NS_sprm::LN_PBrcRight ) ||
4210             ( nSprmNo >= NS_sprm::LN_SBrcTop && nSprmNo <= NS_sprm::LN_SBrcRight ),
4211             "Sprm for border out is of range" );
4212 
4213     WW8_BRC aBrc;
4214 
4215     if (pLine)
4216         aBrc = TranslateBorderLine( *pLine, nDist, bShadow );
4217 
4218     if( bWrtWW8 )
4219     {
4220         // WW97-SprmIds
4221         if ( nSprmNo != 0 )
4222             SwWW8Writer::InsUInt16( rO, nSprmNo );
4223 
4224         rO.Insert( aBrc.aBits1, 2, rO.Count() );
4225         rO.Insert( aBrc.aBits2, 2, rO.Count() );
4226     }
4227     else
4228     {
4229         // WW95-SprmIds
4230         if ( nSprmNo != 0 )
4231             rO.Insert( (sal_uInt8)( nSprmNo ), rO.Count() );
4232         rO.Insert( aBrc.aBits1, 2, rO.Count() );
4233     }
4234 }
4235 
4236 // FormatBox1() ist fuer alle Boxen ausser in Tabellen.
4237 // es wird pO des WW8Writers genommen
Out_SwFmtBox(const SvxBoxItem & rBox,bool bShadow)4238 void WW8Export::Out_SwFmtBox(const SvxBoxItem& rBox, bool bShadow)
4239 {
4240     if ( bOutPageDescs && !bWrtWW8 )
4241         return; // no page ouline in WW6
4242 
4243     static const sal_uInt16 aBorders[] =
4244     {
4245         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
4246     };
4247     static const sal_uInt16 aPBrc[] =
4248     {
4249         NS_sprm::LN_PBrcTop, NS_sprm::LN_PBrcLeft, NS_sprm::LN_PBrcBottom, NS_sprm::LN_PBrcRight
4250     };
4251     static const sal_uInt16 aSBrc[] =
4252     {
4253         NS_sprm::LN_SBrcTop, NS_sprm::LN_SBrcLeft, NS_sprm::LN_SBrcBottom, NS_sprm::LN_SBrcRight
4254     };
4255     static const sal_uInt16 aWW6PBrc[] =
4256     {
4257         38, 39, 40, 41
4258     };
4259 
4260     const sal_uInt16* pBrd = aBorders;
4261     for( sal_uInt16 i = 0; i < 4; ++i, ++pBrd )
4262     {
4263         const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
4264 
4265         sal_uInt16 nSprmNo = 0;
4266         if ( !bWrtWW8 )
4267             nSprmNo = aWW6PBrc[i];
4268         else if ( bOutPageDescs )
4269             nSprmNo = aSBrc[i];
4270         else
4271             nSprmNo = aPBrc[i];
4272 
4273         Out_BorderLine( *pO, pLn, rBox.GetDistance( *pBrd ), nSprmNo, bShadow );
4274     }
4275 }
4276 
4277 // FormatBox2() ist fuer TC-Strukturen in Tabellen. Der Sprm-Opcode
4278 // wird nicht geschrieben, da es in der TC-Structur ohne Opcode gepackt ist.
4279 // dxpSpace wird immer 0, da WW das in Tabellen so verlangt
4280 // ( Tabellenumrandungen fransen sonst aus )
4281 // Ein WW8Bytes-Ptr wird als Ausgabe-Parameter uebergeben
4282 
Out_SwFmtTableBox(WW8Bytes & rO,const SvxBoxItem * pBox)4283 void WW8Export::Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem * pBox )
4284 {
4285     // moeglich und vielleicht besser waere 0xffff
4286     static const sal_uInt16 aBorders[] =
4287     {
4288         BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
4289     };
4290     static const SvxBorderLine aBorderLine;
4291 
4292     const sal_uInt16* pBrd = aBorders;
4293     for( int i = 0; i < 4; ++i, ++pBrd )
4294     {
4295         const SvxBorderLine* pLn;
4296         if (pBox != NULL)
4297             pLn = pBox->GetLine( *pBrd );
4298         else
4299             pLn = & aBorderLine;
4300 
4301         Out_BorderLine(rO, pLn, 0, 0, false);
4302     }
4303 }
4304 
FormatBox(const SvxBoxItem & rBox)4305 void WW8AttributeOutput::FormatBox( const SvxBoxItem& rBox )
4306 {
4307     // Fly um Grafik-> keine Umrandung hier, da
4308     // der GrafikHeader bereits die Umrandung hat
4309     if ( !m_rWW8Export.bOutGrf )
4310     {
4311         bool bShadow = false;
4312         const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_SHADOW );
4313         if ( pItem )
4314         {
4315             const SvxShadowItem* p = (const SvxShadowItem*)pItem;
4316             bShadow = ( p->GetLocation() != SVX_SHADOW_NONE )
4317                       && ( p->GetWidth() != 0 );
4318         }
4319 
4320         m_rWW8Export.Out_SwFmtBox( rBox, bShadow );
4321     }
4322 }
4323 
CurrentPageWidth(SwTwips & rLeft,SwTwips & rRight) const4324 SwTwips WW8Export::CurrentPageWidth(SwTwips &rLeft, SwTwips &rRight) const
4325 {
4326     const SwFrmFmt* pFmt = pAktPageDesc ? &pAktPageDesc->GetMaster()
4327         : &const_cast<const SwDoc *>(pDoc)->GetPageDesc(0).GetMaster();
4328 
4329     const SvxLRSpaceItem& rLR = pFmt->GetLRSpace();
4330     SwTwips nPageSize = pFmt->GetFrmSize().GetWidth();
4331     rLeft = rLR.GetLeft();
4332     rRight = rLR.GetRight();
4333     return nPageSize;
4334 }
4335 
FormatColumns_Impl(sal_uInt16 nCols,const SwFmtCol & rCol,bool bEven,SwTwips nPageSize)4336 void WW8AttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol & rCol, bool bEven, SwTwips nPageSize )
4337 {
4338     // CColumns
4339     if ( m_rWW8Export.bWrtWW8 )
4340         m_rWW8Export.InsUInt16( NS_sprm::LN_SCcolumns );
4341     else
4342         m_rWW8Export.pO->Insert( 144, m_rWW8Export.pO->Count(  ) );
4343     m_rWW8Export.InsUInt16( nCols - 1 );
4344 
4345     // DxaColumns
4346     if ( m_rWW8Export.bWrtWW8 )
4347         m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaColumns );
4348     else
4349         m_rWW8Export.pO->Insert( 145, m_rWW8Export.pO->Count(  ) );
4350     m_rWW8Export.InsUInt16( rCol.GetGutterWidth( true ) );
4351 
4352     // LBetween
4353     if ( m_rWW8Export.bWrtWW8 )
4354         m_rWW8Export.InsUInt16( NS_sprm::LN_SLBetween );
4355     else
4356         m_rWW8Export.pO->Insert( 158, m_rWW8Export.pO->Count(  ) );
4357     m_rWW8Export.pO->Insert( COLADJ_NONE == rCol.GetLineAdj(  )? 0 : 1,
4358                              m_rWW8Export.pO->Count(  ) );
4359 
4360     const SwColumns & rColumns = rCol.GetColumns(  );
4361 
4362     // FEvenlySpaced
4363     if ( m_rWW8Export.bWrtWW8 )
4364         m_rWW8Export.InsUInt16( NS_sprm::LN_SFEvenlySpaced );
4365     else
4366         m_rWW8Export.pO->Insert( 138, m_rWW8Export.pO->Count(  ) );
4367     m_rWW8Export.pO->Insert( bEven ? 1 : 0, m_rWW8Export.pO->Count(  ) );
4368 
4369 #if 0
4370     // FIXME what's the use of this code
4371     if ( bEven )
4372     {
4373         sal_uInt16 nSpace = rColumns[0]->GetRight() + rColumns[1]->GetLeft();
4374         for ( n = 2; n < nCols; n++ )
4375         {
4376             short nDiff = nSpace - ( rColumns[n - 1]->GetRight()
4377                                          + rColumns[n]->GetLeft() );
4378             if (nDiff > 10 || nDiff < -10)
4379             {
4380                 // Toleranz: 10 tw
4381                 bEven = false;
4382                 break;
4383             }
4384         }
4385     }
4386 #endif
4387 
4388     if ( !bEven )
4389     {
4390         for ( sal_uInt16 n = 0; n < nCols; ++n )
4391         {
4392             //sprmSDxaColWidth
4393             if ( m_rWW8Export.bWrtWW8 )
4394                 m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaColWidth );
4395             else
4396                 m_rWW8Export.pO->Insert( 136, m_rWW8Export.pO->Count(  ) );
4397             m_rWW8Export.pO->Insert( ( sal_uInt8 ) n, m_rWW8Export.pO->Count(  ) );
4398             m_rWW8Export.InsUInt16( rCol.
4399                                     CalcPrtColWidth( n,
4400                                                      ( sal_uInt16 ) nPageSize ) );
4401 
4402             if ( n + 1 != nCols )
4403             {
4404                 //sprmSDxaColSpacing
4405                 if ( m_rWW8Export.bWrtWW8 )
4406                     m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaColSpacing );
4407                 else
4408                     m_rWW8Export.pO->Insert( 137,
4409                                              m_rWW8Export.pO->Count(  ) );
4410                 m_rWW8Export.pO->Insert( ( sal_uInt8 ) n,
4411                                          m_rWW8Export.pO->Count(  ) );
4412                 m_rWW8Export.InsUInt16( rColumns[n]->GetRight(  ) +
4413                                         rColumns[n + 1]->GetLeft(  ) );
4414             }
4415         }
4416     }
4417 }
4418 
FormatColumns(const SwFmtCol & rCol)4419 void AttributeOutputBase::FormatColumns( const SwFmtCol& rCol )
4420 {
4421     const SwColumns& rColumns = rCol.GetColumns();
4422 
4423     sal_uInt16 nCols = rColumns.Count();
4424     if ( 1 < nCols && !GetExport( ).bOutFlyFrmAttrs )
4425     {
4426         // dann besorge mal die Seitenbreite ohne Raender !!
4427 
4428 		const SwFrmFmt* pFmt = GetExport( ).pAktPageDesc ? &GetExport( ).pAktPageDesc->GetMaster() : &const_cast<const SwDoc *>(GetExport( ).pDoc)->GetPageDesc(0).GetMaster();
4429 		const SvxFrameDirectionItem &frameDirection = pFmt->GetFrmDir();
4430 		SwTwips nPageSize;
4431 		if ( frameDirection.GetValue() == FRMDIR_VERT_TOP_RIGHT || frameDirection.GetValue() == FRMDIR_VERT_TOP_LEFT )
4432 		{
4433 			const SvxULSpaceItem &rUL = pFmt->GetULSpace();
4434 			nPageSize = pFmt->GetFrmSize().GetHeight();
4435 			nPageSize -= rUL.GetUpper() + rUL.GetLower();
4436 
4437 			const SwFmtHeader *header = dynamic_cast<const SwFmtHeader *>(pFmt->GetAttrSet().GetItem(RES_HEADER));
4438 			if ( header )
4439 			{
4440 				const SwFrmFmt *headerFmt = header->GetHeaderFmt();
4441 				if (headerFmt)
4442 				{
4443 					nPageSize -= headerFmt->GetFrmSize().GetHeight();
4444 				}
4445 			}
4446 			const SwFmtFooter *footer = dynamic_cast<const SwFmtFooter *>(pFmt->GetAttrSet().GetItem(RES_FOOTER));
4447 			if ( footer )
4448 			{
4449 				const SwFrmFmt *footerFmt = footer->GetFooterFmt();
4450 				if ( footerFmt )
4451 				{
4452 					nPageSize -= footerFmt->GetFrmSize().GetHeight();
4453 				}
4454 			}
4455 		}
4456 		else
4457 		{
4458 			const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
4459 			nPageSize = pFmt->GetFrmSize().GetWidth();
4460 			nPageSize -= rLR.GetLeft() + rLR.GetRight();
4461 			//i120133: The Section width should consider page indent value.
4462 			nPageSize -= rCol.GetAdjustValue();
4463 
4464 		}
4465 
4466         // Nachsehen, ob alle Spalten gleich sind
4467         bool bEven = true;
4468         sal_uInt16 n;
4469         sal_uInt16 nColWidth = rCol.CalcPrtColWidth( 0, (sal_uInt16)nPageSize );
4470         for ( n = 1; n < nCols; n++ )
4471         {
4472             short nDiff = nColWidth -
4473                 rCol.CalcPrtColWidth( n, (sal_uInt16)nPageSize );
4474 
4475             if ( nDiff > 10 || nDiff < -10 )      // Toleranz: 10 tw
4476             {
4477                 bEven = false;
4478                 break;
4479             }
4480         }
4481 
4482         FormatColumns_Impl( nCols, rCol, bEven, nPageSize );
4483     }
4484 }
4485 
4486 // "Paragraphs together"
FormatKeep(const SvxFmtKeepItem & rKeep)4487 void WW8AttributeOutput::FormatKeep( const SvxFmtKeepItem& rKeep )
4488 {
4489     // sprmFKeepFollow
4490     if ( m_rWW8Export.bWrtWW8 )
4491         m_rWW8Export.InsUInt16( NS_sprm::LN_PFKeepFollow );
4492     else
4493         m_rWW8Export.pO->Insert( 8, m_rWW8Export.pO->Count() );
4494 
4495     m_rWW8Export.pO->Insert( rKeep.GetValue() ? 1 : 0, m_rWW8Export.pO->Count() );
4496 }
4497 
4498 // exclude a paragraph from Line Numbering
FormatLineNumbering(const SwFmtLineNumber & rNumbering)4499 void WW8AttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
4500 {
4501     // sprmPFNoLineNumb
4502     if( m_rWW8Export.bWrtWW8 )
4503         m_rWW8Export.InsUInt16( NS_sprm::LN_PFNoLineNumb );
4504     else
4505         m_rWW8Export.pO->Insert( 14, m_rWW8Export.pO->Count() );
4506 
4507     m_rWW8Export.pO->Insert( rNumbering.IsCount() ? 0 : 1, m_rWW8Export.pO->Count() );
4508 }
4509 
4510 
4511 /* File PARATR.HXX  */
4512 
ParaLineSpacing_Impl(short nSpace,short nMulti)4513 void WW8AttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
4514 {
4515     // sprmPDyaLine
4516     if ( m_rWW8Export.bWrtWW8 )
4517         m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaLine );
4518     else
4519         m_rWW8Export.pO->Insert( 20, m_rWW8Export.pO->Count() );
4520 
4521     m_rWW8Export.InsUInt16( nSpace );
4522     m_rWW8Export.InsUInt16( nMulti );
4523 }
4524 
ParaLineSpacing(const SvxLineSpacingItem & rSpacing)4525 void AttributeOutputBase::ParaLineSpacing( const SvxLineSpacingItem& rSpacing )
4526 {
4527     short nSpace = 240, nMulti = 0;
4528 
4529     switch ( rSpacing.GetLineSpaceRule() )
4530     {
4531         default:
4532             break;
4533         case SVX_LINE_SPACE_AUTO:
4534         case SVX_LINE_SPACE_FIX:
4535         case SVX_LINE_SPACE_MIN:
4536         {
4537             switch ( rSpacing.GetInterLineSpaceRule() )
4538             {
4539                 case SVX_INTER_LINE_SPACE_FIX:      // unser Durchschuss
4540                 {
4541                     // gibt es aber nicht in WW - also wie kommt man an
4542                     // die MaxLineHeight heran?
4543                     nSpace = (short)rSpacing.GetInterLineSpace();
4544                     sal_uInt16 nScript =
4545                         i18n::ScriptType::LATIN;
4546                     const SwAttrSet *pSet = 0;
4547                     if ( GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwFmt ) )
4548                     {
4549                         const SwFmt *pFmt = (const SwFmt*)( GetExport().pOutFmtNode );
4550                         pSet = &pFmt->GetAttrSet();
4551                     }
4552                     else if ( GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwTxtNode ) )
4553                     {
4554                         const SwTxtNode* pNd = (const SwTxtNode*)GetExport().pOutFmtNode;
4555                         pSet = &pNd->GetSwAttrSet();
4556                         if ( pBreakIt->GetBreakIter().is() )
4557                         {
4558                             nScript = pBreakIt->GetBreakIter()->
4559                                 getScriptType(pNd->GetTxt(), 0);
4560                         }
4561                     }
4562                     ASSERT( pSet, "No attrset for lineheight :-(" );
4563                     if ( pSet )
4564                     {
4565                         nSpace = nSpace + (short)( AttrSetToLineHeight( *GetExport().pDoc,
4566                             *pSet, *Application::GetDefaultDevice(), nScript ) );
4567                     }
4568                 }
4569                 break;
4570             case SVX_INTER_LINE_SPACE_PROP:
4571                 nSpace = (short)( ( 240L * rSpacing.GetPropLineSpace() ) / 100L );
4572                 nMulti = 1;
4573                 break;
4574             default:                    // z.B. Minimum oder FIX?
4575                 if ( SVX_LINE_SPACE_FIX == rSpacing.GetLineSpaceRule() )
4576                     nSpace = -(short)rSpacing.GetLineHeight();
4577                 else
4578                     nSpace = (short)rSpacing.GetLineHeight();
4579                 break;
4580             }
4581         }
4582         break;
4583     }
4584 
4585     ParaLineSpacing_Impl( nSpace, nMulti );
4586 }
4587 
ParaAdjust(const SvxAdjustItem & rAdjust)4588 void WW8AttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
4589 {
4590     // sprmPJc
4591     sal_uInt8 nAdj = 255;
4592     sal_uInt8 nAdjBiDi = 255;
4593     switch ( rAdjust.GetAdjust() )
4594     {
4595         case SVX_ADJUST_LEFT:
4596             nAdj = 0;
4597             nAdjBiDi = 2;
4598             break;
4599         case SVX_ADJUST_RIGHT:
4600             nAdj = 2;
4601             nAdjBiDi = 0;
4602             break;
4603         case SVX_ADJUST_BLOCKLINE:
4604         case SVX_ADJUST_BLOCK:
4605             nAdj = nAdjBiDi = 3;
4606             break;
4607         case SVX_ADJUST_CENTER:
4608             nAdj = nAdjBiDi = 1;
4609             break;
4610         default:
4611             return;    // not a supported Attribut
4612     }
4613 
4614     if ( 255 != nAdj )        // supported Attribut?
4615     {
4616         if ( m_rWW8Export.bWrtWW8 )
4617         {
4618             m_rWW8Export.InsUInt16( NS_sprm::LN_PJc );
4619             m_rWW8Export.pO->Insert( nAdj, m_rWW8Export.pO->Count() );
4620 
4621             /*
4622             Sadly for left to right paragraphs both these values are the same,
4623             for right to left paragraphs the bidi one is the reverse of the
4624             normal one.
4625             */
4626             m_rWW8Export.InsUInt16( NS_sprm::LN_PJcExtra ); //bidi version ?
4627             bool bBiDiSwap = false;
4628             if ( m_rWW8Export.pOutFmtNode )
4629             {
4630                 short nDirection = FRMDIR_HORI_LEFT_TOP;
4631                 if ( m_rWW8Export.pOutFmtNode->ISA( SwTxtNode ) )
4632                 {
4633                     SwPosition aPos(*(const SwCntntNode*)m_rWW8Export.pOutFmtNode);
4634                     nDirection = m_rWW8Export.pDoc->GetTextDirection(aPos);
4635                 }
4636                 else if ( m_rWW8Export.pOutFmtNode->ISA( SwTxtFmtColl ) )
4637                 {
4638                     const SwTxtFmtColl* pC =
4639                         (const SwTxtFmtColl*)m_rWW8Export.pOutFmtNode;
4640                     const SvxFrameDirectionItem &rItem =
4641                         ItemGet<SvxFrameDirectionItem>(*pC, RES_FRAMEDIR);
4642                     nDirection = rItem.GetValue();
4643                 }
4644                 if ( ( nDirection == FRMDIR_HORI_RIGHT_TOP ) ||
4645                      ( nDirection == FRMDIR_ENVIRONMENT && Application::GetSettings().GetLayoutRTL() ) )
4646                 {
4647                     bBiDiSwap = true;
4648                 }
4649             }
4650 
4651             if ( bBiDiSwap )
4652                 m_rWW8Export.pO->Insert( nAdjBiDi, m_rWW8Export.pO->Count() );
4653             else
4654                 m_rWW8Export.pO->Insert( nAdj, m_rWW8Export.pO->Count() );
4655         }
4656         else
4657         {
4658             m_rWW8Export.pO->Insert( 5, m_rWW8Export.pO->Count() );
4659             m_rWW8Export.pO->Insert( nAdj, m_rWW8Export.pO->Count() );
4660         }
4661     }
4662 }
4663 
FormatFrameDirection(const SvxFrameDirectionItem & rDirection)4664 void WW8AttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
4665 {
4666     if ( !m_rWW8Export.bWrtWW8 )   //8+ only
4667         return;
4668 
4669     sal_uInt16 nTextFlow=0;
4670     bool bBiDi = false;
4671     short nDir = rDirection.GetValue();
4672 
4673     if ( nDir == FRMDIR_ENVIRONMENT )
4674     {
4675         if ( m_rWW8Export.bOutPageDescs )
4676             nDir = m_rWW8Export.GetCurrentPageDirection();
4677         else if ( m_rWW8Export.pOutFmtNode )
4678         {
4679             if ( m_rWW8Export.bOutFlyFrmAttrs )  //frame
4680             {
4681                 nDir = m_rWW8Export.TrueFrameDirection(
4682                     *(const SwFrmFmt*)m_rWW8Export.pOutFmtNode );
4683             }
4684             else if ( m_rWW8Export.pOutFmtNode->ISA( SwCntntNode ) )   //pagagraph
4685             {
4686                 const SwCntntNode* pNd =
4687                     (const SwCntntNode*)m_rWW8Export.pOutFmtNode;
4688                 SwPosition aPos( *pNd );
4689                 nDir = m_rWW8Export.pDoc->GetTextDirection( aPos );
4690             }
4691             else if ( m_rWW8Export.pOutFmtNode->ISA( SwTxtFmtColl ) )
4692                 nDir = FRMDIR_HORI_LEFT_TOP;    //what else can we do :-(
4693         }
4694 
4695         if ( nDir == FRMDIR_ENVIRONMENT )
4696             nDir = FRMDIR_HORI_LEFT_TOP;    //Set something
4697     }
4698 
4699     switch ( nDir )
4700     {
4701         default:
4702             //Can't get an unknown type here
4703             ASSERT(false, "Unknown frame direction");
4704         case FRMDIR_HORI_LEFT_TOP:
4705             nTextFlow = 0;
4706             break;
4707         case FRMDIR_HORI_RIGHT_TOP:
4708             nTextFlow = 0;
4709             bBiDi = true;
4710             break;
4711         case FRMDIR_VERT_TOP_LEFT:  //word doesn't have this
4712         case FRMDIR_VERT_TOP_RIGHT:
4713             nTextFlow = 1;
4714             break;
4715     }
4716 
4717     if ( m_rWW8Export.bOutPageDescs )
4718     {
4719         m_rWW8Export.InsUInt16( NS_sprm::LN_STextFlow );
4720         m_rWW8Export.InsUInt16( nTextFlow );
4721         m_rWW8Export.InsUInt16( NS_sprm::LN_SFBiDi );
4722         m_rWW8Export.pO->Insert( bBiDi, m_rWW8Export.pO->Count() );
4723     }
4724     else if ( !m_rWW8Export.bOutFlyFrmAttrs )  //paragraph/style
4725     {
4726         m_rWW8Export.InsUInt16( NS_sprm::LN_PFBiDi );
4727         m_rWW8Export.pO->Insert( bBiDi, m_rWW8Export.pO->Count() );
4728     }
4729 }
4730 
4731 // "Separate paragraphs"
ParaSplit(const SvxFmtSplitItem & rSplit)4732 void WW8AttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
4733 {
4734     // sprmPFKeep
4735     if ( m_rWW8Export.bWrtWW8 )
4736         m_rWW8Export.InsUInt16( NS_sprm::LN_PFKeep );
4737     else
4738         m_rWW8Export.pO->Insert( 7, m_rWW8Export.pO->Count() );
4739     m_rWW8Export.pO->Insert( rSplit.GetValue() ? 0 : 1, m_rWW8Export.pO->Count() );
4740 }
4741 
4742 //  Es wird nur das Item "SvxWidowItem" und nicht die Orphans uebersetzt,
4743 //  da es fuer beides im WW nur ein Attribut "Absatzkontrolle" gibt und
4744 //  im SW wahrscheinlich vom Anwender immer Beide oder keiner gesetzt werden.
ParaWidows(const SvxWidowsItem & rWidows)4745 void WW8AttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
4746 {
4747 // sprmPFWidowControl
4748     if( m_rWW8Export.bWrtWW8 )
4749         m_rWW8Export.InsUInt16( NS_sprm::LN_PFWidowControl );
4750     else
4751         m_rWW8Export.pO->Insert( 51, m_rWW8Export.pO->Count() );
4752     m_rWW8Export.pO->Insert( rWidows.GetValue() ? 1 : 0, m_rWW8Export.pO->Count() );
4753 }
4754 
4755 
4756 class SwWW8WrTabu
4757 {
4758     sal_uInt8* pDel;                 // DelArray
4759     sal_uInt8* pAddPos;              // AddPos-Array
4760     sal_uInt8* pAddTyp;              // AddTyp-Array
4761     sal_uInt16 nAdd;            // so viele Tabs kommen hinzu
4762     sal_uInt16 nDel;            // so viele Tabs fallen weg
4763 public:
4764     SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax);
4765     ~SwWW8WrTabu();
4766 
4767     void Add(const SvxTabStop &rTS, long nAdjustment);
4768     void Del(const SvxTabStop &rTS, long nAdjustment);
4769     void PutAll(WW8Export& rWW8Wrt);
4770 };
4771 
SwWW8WrTabu(sal_uInt16 nDelMax,sal_uInt16 nAddMax)4772 SwWW8WrTabu::SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax)
4773     : nAdd(0), nDel(0)
4774 {
4775     pDel = nDelMax ? new sal_uInt8[nDelMax * 2] : 0;
4776     pAddPos = new sal_uInt8[nAddMax * 2];
4777     pAddTyp = new sal_uInt8[nAddMax];
4778 }
4779 
~SwWW8WrTabu()4780 SwWW8WrTabu::~SwWW8WrTabu()
4781 {
4782     delete[] pAddTyp;
4783     delete[] pAddPos;
4784     delete[] pDel;
4785 }
4786 
4787 // Add( const SvxTabStop & rTS ) fuegt einen Tab in die WW-Struktur ein
Add(const SvxTabStop & rTS,long nAdjustment)4788 void SwWW8WrTabu::Add(const SvxTabStop & rTS, long nAdjustment)
4789 {
4790     // Tab-Position eintragen
4791     ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment),
4792         pAddPos + (nAdd * 2));
4793 
4794     // Tab-Typ eintragen
4795     sal_uInt8 nPara = 0;
4796     switch (rTS.GetAdjustment())
4797     {
4798         case SVX_TAB_ADJUST_RIGHT:
4799             nPara = 2;
4800             break;
4801         case SVX_TAB_ADJUST_CENTER:
4802             nPara = 1;
4803             break;
4804         case SVX_TAB_ADJUST_DECIMAL:
4805             /*
4806             Theres nothing we can do btw the the decimal seperator has been
4807             customized, but if you think different remember that different
4808             locales have different seperators, i.e. german is a , while english
4809             is a .
4810             */
4811             nPara = 3;
4812             break;
4813         default:
4814             break;
4815     }
4816 
4817     switch( rTS.GetFill() )
4818     {
4819         case '.':   // dotted leader
4820             nPara |= 1 << 3;
4821             break;
4822         case '_':   // Single line leader
4823             nPara |= 3 << 3;
4824             break;
4825         case '-':   // hyphenated leader
4826             nPara |= 2 << 3;
4827             break;
4828         case '=':   // heavy line leader
4829             nPara |= 4 << 3;
4830             break;
4831     }
4832 
4833     ByteToSVBT8(nPara, pAddTyp + nAdd);
4834     ++nAdd;
4835 }
4836 
4837 // Del( const SvxTabStop & rTS ) fuegt einen zu loeschenden Tab
4838 // in die WW-Struktur ein
Del(const SvxTabStop & rTS,long nAdjustment)4839 void SwWW8WrTabu::Del(const SvxTabStop &rTS, long nAdjustment)
4840 {
4841     // Tab-Position eintragen
4842     ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment),
4843         pDel + (nDel * 2));
4844     ++nDel;
4845 }
4846 
4847 //  PutAll( WW8Export& rWW8Wrt ) schreibt das Attribut nach rWrt.pO
PutAll(WW8Export & rWrt)4848 void SwWW8WrTabu::PutAll(WW8Export& rWrt)
4849 {
4850     if (!nAdd && !nDel) //It its a no-op
4851         return;
4852     ASSERT(nAdd <= 255, "more than 255 added tabstops ?");
4853     ASSERT(nDel <= 255, "more than 244 removed tabstops ?");
4854     if (nAdd > 255)
4855         nAdd = 255;
4856     if (nDel > 255)
4857         nDel = 255;
4858 
4859     sal_uInt16 nSiz = 2 * nDel + 3 * nAdd + 2;
4860     if (nSiz > 255)
4861         nSiz = 255;
4862 
4863     if (rWrt.bWrtWW8)
4864         rWrt.InsUInt16(NS_sprm::LN_PChgTabsPapx);
4865     else
4866         rWrt.pO->Insert(15, rWrt.pO->Count());
4867     // cch eintragen
4868     rWrt.pO->Insert(msword_cast<sal_uInt8>(nSiz), rWrt.pO->Count());
4869     // DelArr schreiben
4870     rWrt.pO->Insert(msword_cast<sal_uInt8>(nDel), rWrt.pO->Count());
4871     rWrt.OutSprmBytes(pDel, nDel * 2);
4872     // InsArr schreiben
4873     rWrt.pO->Insert(msword_cast<sal_uInt8>(nAdd), rWrt.pO->Count());
4874     rWrt.OutSprmBytes(pAddPos, 2 * nAdd);         // AddPosArray
4875     rWrt.OutSprmBytes(pAddTyp, nAdd);             // AddTypArray
4876 }
4877 
4878 
ParaTabStopAdd(WW8Export & rWrt,const SvxTabStopItem & rTStops,const long nLParaMgn)4879 static void ParaTabStopAdd( WW8Export& rWrt,
4880                             const SvxTabStopItem& rTStops,
4881                             const long nLParaMgn )
4882 {
4883     SwWW8WrTabu aTab( 0, rTStops.Count());
4884 
4885     for( sal_uInt16 n = 0; n < rTStops.Count(); n++ )
4886     {
4887         const SvxTabStop& rTS = rTStops[n];
4888         // Def-Tabs ignorieren
4889         if (SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment())
4890             aTab.Add(rTS, nLParaMgn);
4891     }
4892     aTab.PutAll( rWrt );
4893 }
4894 
lcl_IsEqual(long nOneLeft,const SvxTabStop & rOne,long nTwoLeft,const SvxTabStop & rTwo)4895 bool lcl_IsEqual(long nOneLeft, const SvxTabStop &rOne,
4896     long nTwoLeft, const SvxTabStop &rTwo)
4897 {
4898     return(
4899             nOneLeft == nTwoLeft &&
4900             rOne.GetAdjustment() == rTwo.GetAdjustment() &&
4901             rOne.GetDecimal() == rTwo.GetDecimal() &&
4902             rOne.GetFill() == rTwo.GetFill()
4903           );
4904 }
4905 
ParaTabStopDelAdd(WW8Export & rWrt,const SvxTabStopItem & rTStyle,const long nLStypeMgn,const SvxTabStopItem & rTNew,const long nLParaMgn)4906 static void ParaTabStopDelAdd( WW8Export& rWrt,
4907                                const SvxTabStopItem& rTStyle,
4908                                const long nLStypeMgn,
4909                                const SvxTabStopItem& rTNew,
4910                                const long nLParaMgn )
4911 {
4912     SwWW8WrTabu aTab(rTStyle.Count(), rTNew.Count());
4913 
4914     sal_uInt16 nO = 0;      // rTStyle Index
4915     sal_uInt16 nN = 0;      // rTNew Index
4916 
4917     do {
4918         const SvxTabStop* pTO;
4919         long nOP;
4920         if( nO < rTStyle.Count() )                  // alt noch nicht am Ende ?
4921         {
4922             pTO = &rTStyle[ nO ];
4923             nOP = pTO->GetTabPos() + nLStypeMgn;
4924             if( SVX_TAB_ADJUST_DEFAULT == pTO->GetAdjustment() )
4925             {
4926                 nO++;                                // Default-Tab ignorieren
4927                 continue;
4928             }
4929         }
4930         else
4931         {
4932             pTO = 0;
4933             nOP = LONG_MAX;
4934         }
4935 
4936         const SvxTabStop* pTN;
4937         long nNP;
4938         if( nN < rTNew.Count() )                    // neu noch nicht am Ende
4939         {
4940             pTN = &rTNew[ nN ];
4941             nNP = pTN->GetTabPos() + nLParaMgn;
4942             if( SVX_TAB_ADJUST_DEFAULT == pTN->GetAdjustment() )
4943             {
4944                 nN++;                               // Default-Tab ignorieren
4945                 continue;
4946             }
4947         }
4948         else
4949         {
4950             pTN = 0;
4951             nNP = LONG_MAX;
4952         }
4953 
4954         if( nOP == LONG_MAX && nNP == LONG_MAX )
4955             break;                                  // alles fertig
4956 
4957         if( nOP < nNP )                             // naechster Tab ist alt
4958         {
4959             aTab.Del(*pTO, nLStypeMgn);             // muss geloescht werden
4960             nO++;
4961         }
4962         else if( nNP < nOP )                        // naechster Tab ist neu
4963         {
4964             aTab.Add(*pTN, nLParaMgn);              // muss eigefuegt werden
4965             nN++;
4966         }
4967         else if (lcl_IsEqual(nOP, *pTO, nNP, *pTN)) // Tabs sind gleich:
4968         {
4969             nO++;                                   // nichts zu tun
4970             nN++;
4971         }
4972         else                                        // Tabs selbe Pos, diff Typ
4973         {
4974             aTab.Del(*pTO, nLStypeMgn);             // alten loeschen
4975             aTab.Add(*pTN, nLParaMgn);              // neuen einfuegen
4976             nO++;
4977             nN++;
4978         }
4979     } while( 1 );
4980 
4981     aTab.PutAll( rWrt );
4982 }
4983 
ParaTabStop(const SvxTabStopItem & rTabStops)4984 void WW8AttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStops )
4985 {
4986     const bool bTabsRelativeToIndex = m_rWW8Export.pCurPam->GetDoc()->get( IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT );
4987 
4988     long nCurrentLeft = 0;
4989     if ( bTabsRelativeToIndex )
4990     {
4991         const SfxPoolItem* pLR = m_rWW8Export.HasItem( RES_LR_SPACE );
4992 
4993         if ( pLR != NULL )
4994             nCurrentLeft = static_cast<const SvxLRSpaceItem*>(pLR)->GetTxtLeft();
4995     }
4996 
4997     // --> FLR 2009-03-17 #i100264#
4998     if ( m_rWW8Export.bStyDef &&
4999          m_rWW8Export.pCurrentStyle != NULL &&
5000          m_rWW8Export.pCurrentStyle->DerivedFrom() != NULL )
5001     {
5002         SvxTabStopItem aParentTabs( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
5003         const SwFmt *pParentStyle = m_rWW8Export.pCurrentStyle->DerivedFrom();
5004         {
5005             const SvxTabStopItem* pParentTabs = HasItem<SvxTabStopItem>( pParentStyle->GetAttrSet(), RES_PARATR_TABSTOP );
5006             if ( pParentTabs )
5007             {
5008                 aParentTabs.Insert( pParentTabs );
5009             }
5010         }
5011 
5012         // #120938# - consider left indentation of style and its parent style
5013         long nParentLeft = 0;
5014         if ( bTabsRelativeToIndex )
5015         {
5016             const SvxLRSpaceItem &rStyleLR = ItemGet<SvxLRSpaceItem>( pParentStyle->GetAttrSet(), RES_LR_SPACE );
5017             nParentLeft = rStyleLR.GetTxtLeft();
5018         }
5019 
5020         ParaTabStopDelAdd( m_rWW8Export, aParentTabs, nParentLeft, rTabStops, nCurrentLeft );
5021         return;
5022     }
5023     // <--
5024 
5025     const SvxTabStopItem* pStyleTabs = 0;
5026     if ( !m_rWW8Export.bStyDef && m_rWW8Export.pStyAttr )
5027     {
5028         pStyleTabs = HasItem<SvxTabStopItem>( *m_rWW8Export.pStyAttr, RES_PARATR_TABSTOP );
5029     }
5030 
5031     if ( !pStyleTabs )
5032     {
5033         ParaTabStopAdd(m_rWW8Export, rTabStops, nCurrentLeft);
5034     }
5035     else
5036     {
5037         long nStyleLeft = 0;
5038         if ( bTabsRelativeToIndex )
5039         {
5040             const SvxLRSpaceItem &rStyleLR = ItemGet<SvxLRSpaceItem>(*m_rWW8Export.pStyAttr, RES_LR_SPACE);
5041             nStyleLeft = rStyleLR.GetTxtLeft();
5042         }
5043 
5044         ParaTabStopDelAdd( m_rWW8Export,
5045                            *pStyleTabs, nStyleLeft,
5046                            rTabStops, nCurrentLeft);
5047     }
5048 }
5049 
5050 //-----------------------------------------------------------------------
5051 
OutputItem(const SfxPoolItem & rHt)5052 void AttributeOutputBase::OutputItem( const SfxPoolItem& rHt )
5053 {
5054     // FIXME maybe use 'item_cast', like 'item_cast<SvxCharHiddenItem>( rHt )'?
5055     switch ( rHt.Which() )
5056     {
5057         case RES_CHRATR_CASEMAP:
5058             CharCaseMap( static_cast< const SvxCaseMapItem& >( rHt ) );
5059             break;
5060         case RES_CHRATR_COLOR:
5061             CharColor( static_cast< const SvxColorItem& >( rHt ) );
5062             break;
5063         case RES_CHRATR_CONTOUR:
5064             CharContour( static_cast< const SvxContourItem& >( rHt ) );
5065             break;
5066         case RES_CHRATR_CROSSEDOUT:
5067             CharCrossedOut( static_cast< const SvxCrossedOutItem& >( rHt ) );
5068             break;
5069         case RES_CHRATR_ESCAPEMENT:
5070             CharEscapement( static_cast< const SvxEscapementItem& >( rHt ) );
5071             break;
5072         case RES_CHRATR_FONT:
5073             CharFont( static_cast< const SvxFontItem& >( rHt ) );
5074             break;
5075         case RES_CHRATR_FONTSIZE:
5076             CharFontSize( static_cast< const SvxFontHeightItem& >( rHt ) );
5077             break;
5078         case RES_CHRATR_KERNING:
5079             CharKerning( static_cast< const SvxKerningItem& >( rHt ) );
5080             break;
5081         case RES_CHRATR_LANGUAGE:
5082             CharLanguage( static_cast< const SvxLanguageItem& >( rHt ) );
5083             break;
5084         case RES_CHRATR_POSTURE:
5085             CharPosture( static_cast< const SvxPostureItem& >( rHt ) );
5086             break;
5087         case RES_CHRATR_SHADOWED:
5088             CharShadow( static_cast< const SvxShadowedItem& >( rHt ) );
5089             break;
5090         case RES_CHRATR_UNDERLINE:
5091             CharUnderline( static_cast< const SvxUnderlineItem& >( rHt ) );
5092             break;
5093         case RES_CHRATR_WEIGHT:
5094             CharWeight( static_cast< const SvxWeightItem& >( rHt ) );
5095             break;
5096         case RES_CHRATR_AUTOKERN:
5097             CharAutoKern( static_cast< const SvxAutoKernItem& >( rHt ) );
5098             break;
5099         case RES_CHRATR_BLINK:
5100             CharAnimatedText( static_cast< const SvxBlinkItem& >( rHt ) );
5101             break;
5102         case RES_CHRATR_BACKGROUND:
5103             CharBackground( static_cast< const SvxBrushItem& >( rHt ) );
5104             break;
5105 
5106         case RES_CHRATR_CJK_FONT:
5107             CharFontCJK( static_cast< const SvxFontItem& >( rHt ) );
5108             break;
5109         case RES_CHRATR_CJK_FONTSIZE:
5110             CharFontSizeCJK( static_cast< const SvxFontHeightItem& >( rHt ) );
5111             break;
5112         case RES_CHRATR_CJK_LANGUAGE:
5113             CharLanguageCJK( static_cast< const SvxLanguageItem& >( rHt ) );
5114             break;
5115         case RES_CHRATR_CJK_POSTURE:
5116             CharPostureCJK( static_cast< const SvxPostureItem& >( rHt ) );
5117             break;
5118         case RES_CHRATR_CJK_WEIGHT:
5119             CharWeightCJK( static_cast< const SvxWeightItem& >( rHt ) );
5120             break;
5121 
5122         case RES_CHRATR_CTL_FONT:
5123             CharFontCTL( static_cast< const SvxFontItem& >( rHt ) );
5124             break;
5125         case RES_CHRATR_CTL_FONTSIZE:
5126             CharFontSizeCTL( static_cast< const SvxFontHeightItem& >( rHt ) );
5127             break;
5128         case RES_CHRATR_CTL_LANGUAGE:
5129             CharLanguageCTL( static_cast< const SvxLanguageItem& >( rHt ) );
5130             break;
5131         case RES_CHRATR_CTL_POSTURE:
5132             CharPostureCTL( static_cast< const SvxPostureItem& >( rHt ) );
5133             break;
5134         case RES_CHRATR_CTL_WEIGHT:
5135             CharWeightCTL( static_cast< const SvxWeightItem& >( rHt ) );
5136             break;
5137 
5138         case RES_CHRATR_ROTATE:
5139             CharRotate( static_cast< const SvxCharRotateItem& >( rHt ) );
5140             break;
5141         case RES_CHRATR_EMPHASIS_MARK:
5142             CharEmphasisMark( static_cast< const SvxEmphasisMarkItem& >( rHt ) );
5143             break;
5144         case RES_CHRATR_TWO_LINES:
5145             CharTwoLines( static_cast< const SvxTwoLinesItem& >( rHt ) );
5146             break;
5147         case RES_CHRATR_SCALEW:
5148             CharScaleWidth( static_cast< const SvxCharScaleWidthItem& >( rHt ) );
5149             break;
5150         case RES_CHRATR_RELIEF:
5151             CharRelief( static_cast< const SvxCharReliefItem& >( rHt ) );
5152             break;
5153         case RES_CHRATR_HIDDEN:
5154             CharHidden( static_cast< const SvxCharHiddenItem& >( rHt ) );
5155             break;
5156         case RES_CHRATR_BIDIRTL:
5157 			CharBidiRTL( static_cast< const SfxPoolItem& >( rHt ) );
5158 			break;
5159         case RES_CHRATR_IDCTHINT:
5160 			CharIdctHint( static_cast< const SfxPoolItem& >( rHt ) );
5161 			break;
5162         case RES_TXTATR_INETFMT:
5163             TextINetFormat( static_cast< const SwFmtINetFmt& >( rHt ) );
5164             break;
5165         case RES_TXTATR_CHARFMT:
5166             TextCharFormat( static_cast< const SwFmtCharFmt& >( rHt ) );
5167             break;
5168 
5169         case RES_TXTATR_FIELD:
5170         case RES_TXTATR_ANNOTATION:
5171         case RES_TXTATR_INPUTFIELD:
5172             TextField( static_cast< const SwFmtFld& >( rHt ) );
5173             break;
5174 
5175         case RES_TXTATR_FLYCNT:
5176             TextFlyContent( static_cast< const SwFmtFlyCnt& >( rHt ) );
5177             break;
5178         case RES_TXTATR_FTN:
5179             TextFootnote( static_cast< const SwFmtFtn& >( rHt ) );
5180             break;
5181 
5182         case RES_PARATR_LINESPACING:
5183             ParaLineSpacing( static_cast< const SvxLineSpacingItem& >( rHt ) );
5184             break;
5185         case RES_PARATR_ADJUST:
5186             ParaAdjust( static_cast< const SvxAdjustItem& >( rHt ) );
5187             break;
5188         case RES_PARATR_SPLIT:
5189             ParaSplit( static_cast< const SvxFmtSplitItem& >( rHt ) );
5190             break;
5191         case RES_PARATR_WIDOWS:
5192             ParaWidows( static_cast< const SvxWidowsItem& >( rHt ) );
5193             break;
5194         case RES_PARATR_TABSTOP:
5195             ParaTabStop( static_cast< const SvxTabStopItem& >( rHt ) );
5196             break;
5197         case RES_PARATR_HYPHENZONE:
5198             ParaHyphenZone( static_cast< const SvxHyphenZoneItem& >( rHt ) );
5199             break;
5200         case RES_PARATR_NUMRULE:
5201             ParaNumRule( static_cast< const SwNumRuleItem& >( rHt ) );
5202             break;
5203         case RES_PARATR_SCRIPTSPACE:
5204             ParaScriptSpace( static_cast< const SfxBoolItem& >( rHt ) );
5205             break;
5206         case RES_PARATR_HANGINGPUNCTUATION:
5207             ParaHangingPunctuation( static_cast< const SfxBoolItem& >( rHt ) );
5208             break;
5209         case RES_PARATR_FORBIDDEN_RULES:
5210             ParaForbiddenRules( static_cast< const SfxBoolItem& >( rHt ) );
5211             break;
5212         case RES_PARATR_VERTALIGN:
5213             ParaVerticalAlign( static_cast< const SvxParaVertAlignItem& >( rHt ) );
5214             break;
5215         case RES_PARATR_SNAPTOGRID:
5216             ParaSnapToGrid( static_cast< const SvxParaGridItem& >( rHt ) );
5217             break;
5218 
5219         case RES_FRM_SIZE:
5220             FormatFrameSize( static_cast< const SwFmtFrmSize& >( rHt ) );
5221             break;
5222         case RES_PAPER_BIN:
5223             FormatPaperBin( static_cast< const SvxPaperBinItem& >( rHt ) );
5224             break;
5225         case RES_LR_SPACE:
5226             FormatLRSpace( static_cast< const SvxLRSpaceItem& >( rHt ) );
5227             break;
5228         case RES_UL_SPACE:
5229             FormatULSpace( static_cast< const SvxULSpaceItem& >( rHt ) );
5230             break;
5231         case RES_PAGEDESC:
5232             FormatPageDescription( static_cast< const SwFmtPageDesc& >( rHt ) );
5233             break;
5234         case RES_BREAK:
5235             FormatBreak( static_cast< const SvxFmtBreakItem& >( rHt ) );
5236             break;
5237         case RES_SURROUND:
5238             FormatSurround( static_cast< const SwFmtSurround& >( rHt ) );
5239             break;
5240         case RES_VERT_ORIENT:
5241             FormatVertOrientation( static_cast< const SwFmtVertOrient& >( rHt ) );
5242             break;
5243         case RES_HORI_ORIENT:
5244             FormatHorizOrientation( static_cast< const SwFmtHoriOrient& >( rHt ) );
5245             break;
5246         case RES_ANCHOR:
5247             FormatAnchor( static_cast< const SwFmtAnchor& >( rHt ) );
5248             break;
5249         case RES_BACKGROUND:
5250             FormatBackground( static_cast< const SvxBrushItem& >( rHt ) );
5251             break;
5252         case RES_BOX:
5253             FormatBox( static_cast< const SvxBoxItem& >( rHt ) );
5254             break;
5255         case RES_COL:
5256             FormatColumns( static_cast< const SwFmtCol& >( rHt ) );
5257             break;
5258         case RES_KEEP:
5259             FormatKeep( static_cast< const SvxFmtKeepItem& >( rHt ) );
5260             break;
5261         case RES_TEXTGRID:
5262             FormatTextGrid( static_cast< const SwTextGridItem& >( rHt ) );
5263             break;
5264         case RES_LINENUMBER:
5265             FormatLineNumbering( static_cast< const SwFmtLineNumber& >( rHt ) );
5266             break;
5267         case RES_FRAMEDIR:
5268             FormatFrameDirection( static_cast< const SvxFrameDirectionItem& >( rHt ) );
5269             break;
5270 
5271         default:
5272             OSL_TRACE("Unhandled SfxPoolItem with id %d.\n", rHt.Which() );
5273             break;
5274     }
5275 }
5276 
OutputStyleItemSet(const SfxItemSet & rSet,sal_Bool bDeep,sal_Bool bTestForDefault)5277 void AttributeOutputBase::OutputStyleItemSet( const SfxItemSet& rSet, sal_Bool bDeep, sal_Bool bTestForDefault )
5278 {
5279     // based on OutputItemSet() from wrt_fn.cxx
5280 
5281     const SfxItemPool& rPool = *rSet.GetPool();
5282     const SfxItemSet* pSet = &rSet;
5283     if ( !pSet->Count() )
5284     {
5285         if ( !bDeep )
5286             return;
5287 
5288         while ( 0 != ( pSet = pSet->GetParent() ) && !pSet->Count() )
5289             ;
5290 
5291         if ( !pSet )
5292             return;
5293     }
5294 
5295     const SfxPoolItem* pItem;
5296     if ( !bDeep || !pSet->GetParent() )
5297     {
5298         ASSERT( rSet.Count(), "Wurde doch schon behandelt oder?" );
5299         SfxItemIter aIter( *pSet );
5300         pItem = aIter.GetCurItem();
5301         do {
5302             OutputItem( *pItem );
5303         } while ( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
5304     }
5305     else
5306     {
5307         SfxWhichIter aIter( *pSet );
5308         sal_uInt16 nWhich = aIter.FirstWhich();
5309         while ( nWhich )
5310         {
5311             if ( SFX_ITEM_SET == pSet->GetItemState( nWhich, bDeep, &pItem ) &&
5312                  ( !bTestForDefault ||
5313                    *pItem != rPool.GetDefaultItem( nWhich ) ||
5314                    ( pSet->GetParent() && *pItem != pSet->GetParent()->Get( nWhich ) ) ) )
5315             {
5316                 OutputItem( *pItem );
5317             }
5318             nWhich = aIter.NextWhich();
5319         }
5320     }
5321 }
5322 
5323 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
5324