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