m11-master update
[ooovba.git] / sw / source / filter / ww8 / ww8atr.cxx
blobcf0a141db2ee3d18be16f19c65fc16b7f2d63d82
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ww8atr.cxx,v $
10 * $Revision: 1.113.40.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
36 * Dieses File enthaelt alle Ausgabe-Funktionen des WW8-Writers;
37 * fuer alle Nodes, Attribute, Formate und Chars.
41 #include <hintids.hxx>
43 #ifndef _APP_HXX //autogen
44 #include <vcl/svapp.hxx>
45 #endif
46 #include <vcl/salbtype.hxx>
47 #include <svtools/zformat.hxx>
48 #include <svtools/itemiter.hxx>
49 #include <svx/fontitem.hxx>
50 #ifndef _SVX_TSTPITEM_HXX //autogen
51 #include <svx/tstpitem.hxx>
52 #endif
53 #include <svx/adjitem.hxx>
54 #include <svx/spltitem.hxx>
55 #include <svx/widwitem.hxx>
56 #include <svx/lspcitem.hxx>
57 #include <svx/keepitem.hxx>
58 #include <svx/shaditem.hxx>
59 #include <svx/brshitem.hxx>
60 #include <svx/postitem.hxx>
61 #include <svx/wghtitem.hxx>
62 #include <svx/kernitem.hxx>
63 #include <svx/crsditem.hxx>
64 #include <svx/cmapitem.hxx>
65 #include <svx/wrlmitem.hxx>
66 #include <svx/udlnitem.hxx>
67 #include <svx/langitem.hxx>
68 #include <svx/escpitem.hxx>
69 #include <svx/fhgtitem.hxx>
70 #include <svx/colritem.hxx>
71 #include <svx/hyznitem.hxx>
72 #include <svx/brkitem.hxx>
73 #include <svx/lrspitem.hxx>
74 #include <svx/ulspitem.hxx>
75 #include <svx/boxitem.hxx>
76 #include <svx/cntritem.hxx>
77 #include <svx/shdditem.hxx>
78 #include <svx/akrnitem.hxx>
79 #include <svx/pbinitem.hxx>
80 #ifndef _SVX_EMPHITEM_HXX
81 #include <svx/emphitem.hxx>
82 #endif
83 #include <svx/twolinesitem.hxx>
84 #include <svx/charscaleitem.hxx>
85 #include <svx/charrotateitem.hxx>
86 #include <svx/charreliefitem.hxx>
87 #include <svx/paravertalignitem.hxx>
88 #include <svx/pgrditem.hxx>
89 #include <svx/frmdiritem.hxx>
90 #include <svx/blnkitem.hxx>
91 #include <svx/charhiddenitem.hxx>
92 #include <fmtfld.hxx>
93 #include <fchrfmt.hxx>
94 #include <fmtfsize.hxx>
95 #include <fmtpdsc.hxx>
96 #include <fmtornt.hxx>
97 #include <fmtanchr.hxx>
98 #include <fmtclds.hxx>
99 #include <fmtsrnd.hxx>
100 #include <fmtftn.hxx>
101 #include <fmtflcnt.hxx>
102 #include <frmatr.hxx>
103 #include <swtable.hxx>
104 #include <fmtinfmt.hxx>
105 #include <txtfld.hxx>
106 #include <txtftn.hxx>
107 #include <poolfmt.hxx>
108 #include <doc.hxx> // Doc fuer Fussnoten
109 #include <pam.hxx>
110 #include <paratr.hxx>
111 #include <fldbas.hxx> // fuer SwField ...
112 #include <docufld.hxx> // fuer SwField ...
113 #include <expfld.hxx>
114 #include <pagedesc.hxx> // fuer SwPageDesc...
115 #include <flddat.hxx> // fuer Datum-Felder
116 #include <ndtxt.hxx> // fuer Numrules
117 #include <fmthbsh.hxx>
118 #include <swrect.hxx>
119 #include <reffld.hxx>
120 #include <ftninfo.hxx>
121 #include <charfmt.hxx>
122 #include <section.hxx>
123 #include <lineinfo.hxx>
124 #include <fmtline.hxx>
125 #include <tox.hxx>
126 #include <fmtftntx.hxx>
127 #include <breakit.hxx>
128 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
129 #include <com/sun/star/i18n/ScriptType.hdl>
130 #endif
131 #include <unotools/localedatawrapper.hxx>
132 #include <tgrditem.hxx>
133 #include <flddropdown.hxx>
134 #include <chpfld.hxx>
135 #include <fmthdft.hxx>
137 #if OSL_DEBUG_LEVEL > 1
138 # include <fmtcntnt.hxx>
139 #endif
140 #include "writerhelper.hxx"
141 #include "writerwordglue.hxx"
142 #include "wrtww8.hxx"
143 #include "ww8par.hxx"
144 #include "fields.hxx"
145 #include <vcl/outdev.hxx>
146 #include <i18npool/mslangid.hxx>
148 using namespace ::com::sun::star;
149 using namespace nsFieldFlags;
150 using namespace nsSwDocInfoSubType;
154 * um nicht immer wieder nach einem Update festzustellen, das irgendwelche
155 * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle
156 * definiert und mit der akt. verglichen. Bei unterschieden wird der
157 * Compiler schon meckern.
159 * diese Section und die dazugeherigen Tabellen muessen in folgenden Files
160 * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx
163 #if !defined(MSC) && !defined(UNX) && !defined(PPC) && !defined(CSET) && !defined(__MWERKS__) && !defined(WTC) && !defined(__MINGW32__) && !defined(OS2)
165 #define ATTRFNTAB_SIZE 130
166 #if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN
167 # error "Attribut-Tabelle ist ungueltigt. Wurden neue Hint-ID's zugefuegt ??"
168 #endif
170 #define NODETAB_SIZE 3
171 #if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN
172 # error "Node-Tabelle ist ungueltigt. Wurden neue Hint-ID's zugefuegt ??"
173 #endif
175 #endif
177 using namespace sw::util;
178 using namespace sw::types;
179 //------------------------------------------------------------
180 // Forward-Declarationen
181 //------------------------------------------------------------
182 static Writer& OutWW8_SwFmtBreak( Writer& rWrt, const SfxPoolItem& rHt );
183 static Writer& OutWW8_SwNumRuleItem( Writer& rWrt, const SfxPoolItem& rHt );
186 Sadly word does not have two different sizes for asian font size and western
187 font size, it has to different fonts, but not sizes, so we have to use our
188 guess as to the script used and disable the export of one type. The same
189 occurs for font weight and posture (bold and italic)
191 In addition WW7- has only one character language identifier while WW8+ has two
193 bool SwWW8Writer::CollapseScriptsforWordOk(USHORT nScript, USHORT nWhich)
195 bool bRet = true;
196 if (nScript == i18n::ScriptType::ASIAN)
198 //for asian in ww8, there is only one fontsize
199 //and one fontstyle (posture/weight) for ww6
200 //there is the additional problem that there
201 //is only one font setting for all three scripts
202 switch (nWhich)
204 case RES_CHRATR_FONTSIZE:
205 case RES_CHRATR_POSTURE:
206 case RES_CHRATR_WEIGHT:
207 bRet = false;
208 break;
209 case RES_CHRATR_LANGUAGE:
210 case RES_CHRATR_CTL_FONT:
211 case RES_CHRATR_CTL_FONTSIZE:
212 case RES_CHRATR_CTL_LANGUAGE:
213 case RES_CHRATR_CTL_POSTURE:
214 case RES_CHRATR_CTL_WEIGHT:
215 if (bWrtWW8 == 0)
216 bRet = false;
217 default:
218 break;
221 else if (nScript == i18n::ScriptType::COMPLEX)
223 //Complex is ok in ww8, but for ww6 there is only
224 //one font, one fontsize, one fontsize (weight/posture)
225 //and only one language
226 if (bWrtWW8 == 0)
228 switch (nWhich)
230 case RES_CHRATR_CJK_FONT:
231 case RES_CHRATR_CJK_FONTSIZE:
232 case RES_CHRATR_CJK_POSTURE:
233 case RES_CHRATR_CJK_WEIGHT:
234 case RES_CHRATR_CJK_LANGUAGE:
235 case RES_CHRATR_FONT:
236 case RES_CHRATR_FONTSIZE:
237 case RES_CHRATR_POSTURE:
238 case RES_CHRATR_WEIGHT:
239 case RES_CHRATR_LANGUAGE:
240 bRet = false;
241 break;
242 default:
243 break;
247 else
249 //for western in ww8, there is only one fontsize
250 //and one fontstyle (posture/weight) for ww6
251 //there is the additional problem that there
252 //is only one font setting for all three scripts
253 switch (nWhich)
255 case RES_CHRATR_CJK_FONTSIZE:
256 case RES_CHRATR_CJK_POSTURE:
257 case RES_CHRATR_CJK_WEIGHT:
258 bRet = false;
259 break;
260 case RES_CHRATR_CJK_LANGUAGE:
261 case RES_CHRATR_CTL_FONT:
262 case RES_CHRATR_CTL_FONTSIZE:
263 case RES_CHRATR_CTL_LANGUAGE:
264 case RES_CHRATR_CTL_POSTURE:
265 case RES_CHRATR_CTL_WEIGHT:
266 if (bWrtWW8 == 0)
267 bRet = false;
268 default:
269 break;
272 return bRet;
275 //------------------------------------------------------------
276 // Hilfsroutinen fuer Styles
277 //------------------------------------------------------------
279 void SwWW8Writer::ExportPoolItemsToCHP(sw::PoolItems &rItems, USHORT nScript)
281 sw::cPoolItemIter aEnd = rItems.end();
282 for (sw::cPoolItemIter aI = rItems.begin(); aI != aEnd; ++aI)
284 const SfxPoolItem *pItem = aI->second;
285 USHORT nWhich = pItem->Which();
286 if (FnAttrOut pOut = aWW8AttrFnTab[nWhich - RES_CHRATR_BEGIN])
288 if (nWhich < RES_CHRATR_BEGIN || nWhich >= RES_TXTATR_END)
289 continue;
290 if (SwWW8Writer::CollapseScriptsforWordOk(nScript, nWhich))
291 (*pOut)(*this, *pItem);
297 * Format wie folgt ausgeben:
298 * - gebe die Attribute aus; ohne Parents!
301 void SwWW8Writer::Out_SfxItemSet(const SfxItemSet& rSet, bool bPapFmt,
302 bool bChpFmt, USHORT nScript)
304 if (rSet.Count())
306 const SfxPoolItem* pItem;
307 FnAttrOut pOut;
309 pISet = &rSet; // fuer Doppel-Attribute
311 //If frame dir is set, but not adjust, then force adjust as well
312 if (bPapFmt && SFX_ITEM_SET == rSet.GetItemState(RES_FRAMEDIR, false))
314 //No explicit adjust set ?
315 if (SFX_ITEM_SET != rSet.GetItemState(RES_PARATR_ADJUST, false))
317 if (0 != (pItem = rSet.GetItem(RES_PARATR_ADJUST)))
319 // then set the adjust used by the parent format
320 pOut = aWW8AttrFnTab[ static_cast< USHORT >(RES_PARATR_ADJUST) - RES_CHRATR_BEGIN];
321 (*pOut)( *this, *pItem );
326 if (bPapFmt && SFX_ITEM_SET == rSet.GetItemState(RES_PARATR_NUMRULE,
327 false, &pItem))
329 pOut = aWW8AttrFnTab[ static_cast< USHORT >(RES_PARATR_NUMRULE) - RES_CHRATR_BEGIN ];
330 (*pOut)( *this, *pItem );
331 // switch off the numerbering?
332 if( !((SwNumRuleItem*)pItem)->GetValue().Len() && SFX_ITEM_SET
333 != rSet.GetItemState( RES_LR_SPACE, false) && SFX_ITEM_SET
334 == rSet.GetItemState( RES_LR_SPACE, true, &pItem ) )
336 // the set the LR-Space of the parentformat!
337 pOut = aWW8AttrFnTab[ static_cast< USHORT >(RES_LR_SPACE) - RES_CHRATR_BEGIN ];
338 (*pOut)( *this, *pItem );
342 sw::PoolItems aItems;
343 GetPoolItems(rSet, aItems);
344 if (bChpFmt)
345 ExportPoolItemsToCHP(aItems, nScript);
347 sw::cPoolItemIter aEnd = aItems.end();
348 for (sw::cPoolItemIter aI = aItems.begin(); aI != aEnd; ++aI)
350 pItem = aI->second;
351 USHORT nWhich = pItem->Which();
352 pOut = aWW8AttrFnTab[nWhich - RES_CHRATR_BEGIN];
353 if( 0 != pOut && (!bPapFmt || RES_PARATR_NUMRULE != nWhich ))
355 bool bPap = nWhich >= RES_PARATR_BEGIN
356 && nWhich < RES_FRMATR_END;
357 if (bPapFmt && bPap)
358 (*pOut)(*this, *pItem);
361 pISet = 0; // fuer Doppel-Attribute
365 void SwWW8Writer::GatherChapterFields()
367 //If the header/footer contains a chapter field
368 SwClientIter aIter(*pDoc->GetSysFldType(RES_CHAPTERFLD));
369 const SwClient *pField = aIter.First(TYPE(SwFmtFld));
370 while (pField)
372 const SwFmtFld* pFld = (const SwFmtFld*)(pField);
373 if (const SwTxtFld *pTxtFld = pFld->GetTxtFld())
375 const SwTxtNode &rTxtNode = pTxtFld->GetTxtNode();
376 maChapterFieldLocs.push_back(rTxtNode.GetIndex());
378 pField = aIter.Next();
382 bool SwWW8Writer::CntntContainsChapterField(const SwFmtCntnt &rCntnt) const
384 bool bRet = false;
385 if (const SwNodeIndex* pSttIdx = rCntnt.GetCntntIdx())
387 SwNodeIndex aIdx(*pSttIdx, 1);
388 SwNodeIndex aEnd(*pSttIdx->GetNode().EndOfSectionNode());
389 ULONG nStart = aIdx.GetIndex();
390 ULONG nEnd = aEnd.GetIndex();
391 //If the header/footer contains a chapter field
392 mycCFIter aIEnd = maChapterFieldLocs.end();
393 for (mycCFIter aI = maChapterFieldLocs.begin(); aI != aIEnd; ++aI)
395 if ((nStart <= *aI) && (*aI <= nEnd))
397 bRet = true;
398 break;
402 return bRet;
405 bool SwWW8Writer::FmtHdFtContainsChapterField(const SwFrmFmt &rFmt) const
407 if (maChapterFieldLocs.empty())
408 return false;
409 bool bRet = false;
411 const SwFrmFmt *pFmt = 0;
412 if (0 != (pFmt = rFmt.GetHeader().GetHeaderFmt()))
413 bRet = CntntContainsChapterField(pFmt->GetCntnt());
414 if (!bRet && 0 != (pFmt = rFmt.GetFooter().GetFooterFmt()))
415 bRet = CntntContainsChapterField(pFmt->GetCntnt());
417 return bRet;
420 bool SwWW8Writer::SetAktPageDescFromNode(const SwNode &rNd)
422 bool bNewPageDesc = false;
423 const SwPageDesc* pCurrent = SwPageDesc::GetPageDescOfNode(rNd);
424 ASSERT(pCurrent && pAktPageDesc, "Not possible surely");
425 if (pAktPageDesc && pCurrent)
427 if (pCurrent != pAktPageDesc)
429 if (pAktPageDesc->GetFollow() != pCurrent)
430 bNewPageDesc = true;
431 else
433 const SwFrmFmt& rTitleFmt = pAktPageDesc->GetMaster();
434 const SwFrmFmt& rFollowFmt = pCurrent->GetMaster();
436 bNewPageDesc = !IsPlausableSingleWordSection(rTitleFmt,
437 rFollowFmt);
439 pAktPageDesc = pCurrent;
441 else
443 const SwFrmFmt &rFmt = pCurrent->GetMaster();
444 bNewPageDesc = FmtHdFtContainsChapterField(rFmt);
447 return bNewPageDesc;
450 // Da WW nur Break-After ( Pagebreak und Sectionbreaks ) kennt, im SW aber
451 // Bagebreaks "vor" und "nach" und Pagedescs nur "vor" existieren, werden
452 // die Breaks 2* durchgeklimpert, naemlich vor und hinter jeder Zeile.
453 // Je nach BreakTyp werden sie vor oder nach der Zeile gesetzt.
454 // Es duerfen nur Funktionen gerufen werden, die nicht in den
455 // Ausgabebereich pO schreiben, da dieser nur einmal fuer CHP und PAP existiert
456 // und damit im falschen landen wuerden.
457 void SwWW8Writer::Out_SfxBreakItems(const SfxItemSet *pSet, const SwNode& rNd)
459 bool bAllowOutputPageDesc = false;
460 if (!bStyDef && !bOutKF && !bInWriteEscher && !bOutPageDescs)
461 bAllowOutputPageDesc = true;
463 if (!bAllowOutputPageDesc)
464 return;
466 bBreakBefore = true;
468 bool bNewPageDesc = false;
469 const SfxPoolItem* pItem=0;
470 const SwFmtPageDesc *pPgDesc=0;
472 //Output a sectionbreak if theres a new pagedesciptor. otherwise output a
473 //pagebreak if there is a pagebreak here, unless the new page (follow
474 //style) is different to the current one, in which case plump for a
475 //section.
476 bool bBreakSet = false;
478 if (pSet && pSet->Count())
480 if (SFX_ITEM_SET == pSet->GetItemState(RES_PAGEDESC, false, &pItem)
481 && ((SwFmtPageDesc*)pItem)->GetRegisteredIn())
483 bBreakSet = true;
484 bNewPageDesc = true;
485 pPgDesc = (const SwFmtPageDesc*)pItem;
486 pAktPageDesc = pPgDesc->GetPageDesc();
488 else if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false, &pItem))
490 // --> FME 2007-05-30 #146867# Word does not like hard break attributes in some table cells
491 bool bRemoveHardBreakInsideTable = false;
492 if ( bOutTable )
494 const SwTableNode* pTableNode = rNd.FindTableNode();
495 if ( pTableNode )
497 const SwTableBox* pBox = rNd.GetTblBox();
498 const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0;
499 // but only for non-complex tables
500 if ( pLine && !pLine->GetUpper() )
502 // check if box is not first in that line:
503 if ( 0 < pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() )
505 bRemoveHardBreakInsideTable = true;
510 // <--
512 bBreakSet = true;
514 if ( !bRemoveHardBreakInsideTable )
516 ASSERT(pAktPageDesc, "should not be possible");
518 If because of this pagebreak the page desc following the page
519 break is the follow style of the current page desc then output a
520 section break using that style instead. At least in those cases
521 we end up with the same style in word and writer, nothing can be
522 done when it happens when we get a new pagedesc because we
523 overflow from the first page style.
525 if (pAktPageDesc)
527 // --> OD 2007-05-30 #i76301#
528 // assure that there is a page break before set at the node.
529 const SvxFmtBreakItem* pBreak = dynamic_cast<const SvxFmtBreakItem*>(pItem);
530 if ( pBreak &&
531 pBreak->GetBreak() == SVX_BREAK_PAGE_BEFORE )
533 bNewPageDesc = SetAktPageDescFromNode(rNd);
535 // <--
537 if (!bNewPageDesc)
538 OutWW8_SwFmtBreak( *this, *pItem );
544 #i9301#
545 No explicit page break, lets see if the style had one and we've moved to a
546 new page style because of it, if we have to then we take the opportunity to
547 set the equivalent word section here. We *could* do it for every paragraph
548 that moves onto a new page because of layout, but that would be insane.
550 bool bHackInBreak = false;
551 if (!bBreakSet)
553 if (const SwCntntNode *pNd = rNd.GetCntntNode())
555 const SvxFmtBreakItem &rBreak =
556 ItemGet<SvxFmtBreakItem>(*pNd, RES_BREAK);
557 if (rBreak.GetBreak() == SVX_BREAK_PAGE_BEFORE)
558 bHackInBreak = true;
559 else
560 { // Even a pagedesc item is set, the break item can be set 'NONE',
561 // but a pagedesc item is an implicit page break before...
562 const SwFmtPageDesc &rPageDesc =
563 ItemGet<SwFmtPageDesc>( *pNd, RES_PAGEDESC );
564 if( rPageDesc.GetRegisteredIn() )
565 bHackInBreak = true;
570 if (bHackInBreak)
572 ASSERT(pAktPageDesc, "should not be possible");
573 if (pAktPageDesc)
574 bNewPageDesc = SetAktPageDescFromNode(rNd);
577 if (bNewPageDesc && pAktPageDesc)
579 // --> OD 2007-05-29 #i76300#
580 // code moved code to method <SwWW8Writer::PrepareNewPageDesc(..)>
581 // // Die PageDescs werden beim Auftreten von PageDesc-Attributen nur in
582 // // WW8Writer::pSepx mit der entsprechenden Position eingetragen. Das
583 // // Aufbauen und die Ausgabe der am PageDesc haengenden Attribute und
584 // // Kopf/Fusszeilen passiert nach dem Haupttext und seinen Attributen.
586 // ULONG nFcPos = ReplaceCr(0x0c); // Page/Section-Break
588 // const SwSectionFmt *pFmt = 0;
589 // const SwSectionNode* pSect = rNd.FindSectionNode();
590 // if (pSect && CONTENT_SECTION == pSect->GetSection().GetType())
591 // pFmt = pSect->GetSection().GetFmt();
593 // // tatsaechlich wird hier NOCH NICHTS ausgegeben, sondern
594 // // nur die Merk-Arrays aCps, aSects entsprechend ergaenzt
595 // if (nFcPos)
596 // {
597 // const SwFmtLineNumber *pNItem = 0;
598 // if (pSet)
599 // pNItem = &(ItemGet<SwFmtLineNumber>(*pSet,RES_LINENUMBER));
600 // else if (const SwCntntNode *pNd = rNd.GetCntntNode())
601 // pNItem = &(ItemGet<SwFmtLineNumber>(*pNd,RES_LINENUMBER));
602 // ULONG nLnNm = pNItem ? pNItem->GetStartValue() : 0;
604 // if (pPgDesc)
605 // pSepx->AppendSep(Fc2Cp(nFcPos), *pPgDesc, rNd, pFmt, nLnNm);
606 // else
607 // pSepx->AppendSep(Fc2Cp(nFcPos), pAktPageDesc, rNd, pFmt, nLnNm);
608 // }
609 PrepareNewPageDesc( pSet, rNd, pPgDesc, pAktPageDesc );
611 bBreakBefore = false;
614 // --> OD 2007-05-29 #i76300#
615 bool SwWW8Writer::Out_FollowPageDesc( const SfxItemSet* pSet,
616 const SwTxtNode* pNd )
618 bool bRet = false;
620 if ( pNd &&
621 pAktPageDesc &&
622 pAktPageDesc != pAktPageDesc->GetFollow() )
624 PrepareNewPageDesc( pSet, *pNd, 0, pAktPageDesc->GetFollow() );
625 bRet = true;
628 return bRet;
631 // initial version by extracting corresponding code from method <SwWW8Writer::Out_SfxBreakItems(..)>
632 void SwWW8Writer::PrepareNewPageDesc( const SfxItemSet*pSet,
633 const SwNode& rNd,
634 const SwFmtPageDesc* pNewPgDescFmt,
635 const SwPageDesc* pNewPgDesc )
637 // Die PageDescs werden beim Auftreten von PageDesc-Attributen nur in
638 // WW8Writer::pSepx mit der entsprechenden Position eingetragen. Das
639 // Aufbauen und die Ausgabe der am PageDesc haengenden Attribute und
640 // Kopf/Fusszeilen passiert nach dem Haupttext und seinen Attributen.
642 ULONG nFcPos = ReplaceCr(0x0c); // Page/Section-Break
644 const SwSectionFmt* pFmt = 0;
645 const SwSectionNode* pSect = rNd.FindSectionNode();
646 if ( pSect &&
647 CONTENT_SECTION == pSect->GetSection().GetType() )
649 pFmt = pSect->GetSection().GetFmt();
652 // tatsaechlich wird hier NOCH NICHTS ausgegeben, sondern
653 // nur die Merk-Arrays aCps, aSects entsprechend ergaenzt
654 if ( nFcPos )
656 const SwFmtLineNumber* pNItem = 0;
657 if ( pSet )
659 pNItem = &(ItemGet<SwFmtLineNumber>(*pSet,RES_LINENUMBER));
661 else if (const SwCntntNode *pNd = rNd.GetCntntNode())
663 pNItem = &(ItemGet<SwFmtLineNumber>(*pNd,RES_LINENUMBER));
665 const ULONG nLnNm = pNItem ? pNItem->GetStartValue() : 0;
667 if ( pNewPgDescFmt )
669 pSepx->AppendSep(Fc2Cp(nFcPos), *pNewPgDescFmt, rNd, pFmt, nLnNm);
671 else if ( pNewPgDesc )
673 pSepx->AppendSep(Fc2Cp(nFcPos), pNewPgDesc, rNd, pFmt, nLnNm);
675 else
677 ASSERT( false, "<SwWW8Writer::PrepareNewPageDesc(..)> - misusage: neither page desc format nor page desc provided." );
681 // <--
684 void SwWW8Writer::CorrTabStopInSet(SfxItemSet& rSet, USHORT nAbsLeft)
686 const SvxTabStopItem *pItem =
687 sw::util::HasItem<SvxTabStopItem>(rSet, RES_PARATR_TABSTOP);
689 if (pItem)
691 // dann muss das fuer die Ausgabe korrigiert werden
692 SvxTabStopItem aTStop(*pItem);
693 for(USHORT nCnt = 0; nCnt < aTStop.Count(); ++nCnt)
695 SvxTabStop& rTab = (SvxTabStop&)aTStop[ nCnt ];
696 if( SVX_TAB_ADJUST_DEFAULT != rTab.GetAdjustment() &&
697 rTab.GetTabPos() >= nAbsLeft )
698 rTab.GetTabPos() -= nAbsLeft;
699 else
701 aTStop.Remove( nCnt );
702 --nCnt;
705 rSet.Put( aTStop );
709 BYTE SwWW8Writer::GetNumId( USHORT eNumType )
711 BYTE nRet = 0;
712 switch( eNumType )
714 case SVX_NUM_CHARS_UPPER_LETTER:
715 case SVX_NUM_CHARS_UPPER_LETTER_N: nRet = 3; break;
716 case SVX_NUM_CHARS_LOWER_LETTER:
717 case SVX_NUM_CHARS_LOWER_LETTER_N: nRet = 4; break;
718 case SVX_NUM_ROMAN_UPPER: nRet = 1; break;
719 case SVX_NUM_ROMAN_LOWER: nRet = 2; break;
721 case SVX_NUM_BITMAP:
722 case SVX_NUM_CHAR_SPECIAL: nRet = 23; break;
724 // nix, macht WW undokumentiert auch so
725 case SVX_NUM_NUMBER_NONE: nRet = 0xff; break;
727 return nRet;
730 void SwWW8Writer::ExportOutlineNumbering(BYTE nLvl, const SwNumFmt &rNFmt,
731 const SwFmt &rFmt)
733 if (nLvl >= WW8ListManager::nMaxLevel)
734 nLvl = WW8ListManager::nMaxLevel-1;
736 if( bWrtWW8 )
738 // write sprmPOutLvl sprmPIlvl and sprmPIlfo
739 SwWW8Writer::InsUInt16( *pO, 0x2640 );
740 pO->Insert( nLvl, pO->Count() );
741 SwWW8Writer::InsUInt16( *pO, 0x260a );
742 pO->Insert( nLvl, pO->Count() );
743 SwWW8Writer::InsUInt16( *pO, 0x460b );
744 SwWW8Writer::InsUInt16( *pO, 1 + GetId(
745 *pDoc->GetOutlineNumRule() ) );
747 else
749 Out_SwNumLvl( nLvl );
750 // --> OD 2008-06-03 #i86652#
751 // if (rNFmt.GetAbsLSpace())
752 if ( rNFmt.GetPositionAndSpaceMode() ==
753 SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&
754 rNFmt.GetAbsLSpace() )
755 // <--
757 SwNumFmt aNumFmt(rNFmt);
758 const SvxLRSpaceItem& rLR =
759 ItemGet<SvxLRSpaceItem>(rFmt, RES_LR_SPACE);
760 aNumFmt.SetAbsLSpace(writer_cast<short>(
761 aNumFmt.GetAbsLSpace() + rLR.GetLeft()));
762 Out_NumRuleAnld( *pDoc->GetOutlineNumRule(),
763 aNumFmt, nLvl );
765 else
766 Out_NumRuleAnld( *pDoc->GetOutlineNumRule(),
767 rNFmt, nLvl );
771 // --> OD 2007-06-04 #i77805#
772 bool SwWW8Writer::DisallowInheritingOutlineNumbering(const SwFmt &rFmt)
774 bool bRet( false );
776 //If there is no numbering on this fmt, but its parent was outline
777 //numbered, then in writer this is no inheritied, but in word it would
778 //be, so we must export "no numbering" and "body level" to make word
779 //behave like writer (see #i25755)
780 if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
782 if (const SwFmt *pParent = rFmt.DerivedFrom())
784 //BYTE nLvl = ((const SwTxtFmtColl*)pParent)->GetOutlineLevel(); //#outline level,removed by zhaojianwei
785 //if (MAXLEVEL > nLvl)
786 //{ //<-end, ->add by zhaojianwei
787 if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
788 { //<-end,zhaojianwei
789 if (bWrtWW8)
791 SwWW8Writer::InsUInt16(*pO, 0x2640);
792 pO->Insert(BYTE(9), pO->Count());
793 SwWW8Writer::InsUInt16(*pO, 0x460b);
794 SwWW8Writer::InsUInt16(*pO, 0);
796 bRet = true;
798 /*whats the winword 6 way to do this ?*/
803 return bRet;
805 // <--
807 void SwWW8Writer::Out_SwFmt(const SwFmt& rFmt, bool bPapFmt, bool bChpFmt,
808 bool bFlyFmt)
810 bool bCallOutSet = true;
811 const SwModify* pOldMod = pOutFmtNode;
812 pOutFmtNode = &rFmt;
814 switch( rFmt.Which() )
816 case RES_CONDTXTFMTCOLL:
817 case RES_TXTFMTCOLL:
818 if( bPapFmt )
820 //BYTE nLvl = ((const SwTxtFmtColl&)rFmt).GetOutlineLevel(); //#outline level,removed by zhaojianwei
821 //if (MAXLEVEL > nLvl)
822 //{ //<-end, ->add by zhaojianwei
823 if (((const SwTxtFmtColl&)rFmt).IsAssignedToListLevelOfOutlineStyle())
825 int nLvl = ((const SwTxtFmtColl&)rFmt).GetAssignedOutlineStyleLevel(); //<-end,zhaojianwei
827 //if outline numbered
828 // if Write StyleDefinition then write the OutlineRule
829 const SwNumFmt& rNFmt = pDoc->GetOutlineNumRule()->Get(static_cast<USHORT>(nLvl));
830 if (bStyDef)
831 ExportOutlineNumbering(static_cast<BYTE>(nLvl), rNFmt, rFmt);
833 // --> OD 2008-06-03 #i86652#
834 // if (rNFmt.GetAbsLSpace())
835 if ( rNFmt.GetPositionAndSpaceMode() ==
836 SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&
837 rNFmt.GetAbsLSpace() )
838 // <--
840 SfxItemSet aSet( rFmt.GetAttrSet() );
841 SvxLRSpaceItem aLR(
842 ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
844 aLR.SetTxtLeft( aLR.GetTxtLeft() + rNFmt.GetAbsLSpace() );
845 aLR.SetTxtFirstLineOfst( GetWordFirstLineOffset(rNFmt));
847 aSet.Put( aLR );
848 SwWW8Writer::CorrTabStopInSet( aSet, rNFmt.GetAbsLSpace() );
849 Out_SfxItemSet( aSet, bPapFmt, bChpFmt,
850 i18n::ScriptType::LATIN);
851 bCallOutSet = false;
854 else
856 //otherwise we might have to remove outline numbering from
857 //what gets exported if the parent style was outline numbered
858 // --> OD 2007-06-04 #i77805#
859 // If inherited outline numbering is suppress, the left/right
860 // margins has to be exported explicitly.
861 if ( bStyDef && DisallowInheritingOutlineNumbering(rFmt) )
863 SfxItemSet aSet( rFmt.GetAttrSet() );
864 SvxLRSpaceItem aLR(
865 ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
866 aSet.Put( aLR );
867 Out_SfxItemSet( aSet, bPapFmt, bChpFmt,
868 com::sun::star::i18n::ScriptType::LATIN);
869 bCallOutSet = false;
871 // <--
874 break;
876 case RES_CHRFMT:
877 break;
878 case RES_FLYFRMFMT:
879 if (bFlyFmt)
881 ASSERT(mpParentFrame, "No parent frame, all broken");
883 if (mpParentFrame)
885 const SwFrmFmt &rFrmFmt = mpParentFrame->GetFrmFmt();
887 SfxItemSet aSet(pDoc->GetAttrPool(), RES_FRMATR_BEGIN,
888 RES_FRMATR_END-1);
889 aSet.Set(rFrmFmt.GetAttrSet());
891 // Fly als Zeichen werden bei uns zu Absatz-gebundenen
892 // jetzt den Abstand vom Absatz-Rand setzen
893 if (pFlyOffset)
895 aSet.Put(SwFmtHoriOrient(pFlyOffset->X()));
896 aSet.Put(SwFmtVertOrient(pFlyOffset->Y()));
897 SwFmtAnchor aAnchor(rFrmFmt.GetAnchor());
898 aAnchor.SetType(eNewAnchorType);
899 aSet.Put(aAnchor);
902 if (SFX_ITEM_SET != aSet.GetItemState(RES_SURROUND))
903 aSet.Put(SwFmtSurround(SURROUND_NONE));
905 bOutFlyFrmAttrs = true;
906 //script doesn't matter if not exporting chp
907 Out_SfxItemSet(aSet, true, false,
908 i18n::ScriptType::LATIN);
909 bOutFlyFrmAttrs = false;
911 bCallOutSet = false;
914 break;
915 default:
916 ASSERT( !this, "Was wird hier ausgegeben ??? " );
917 break;
920 if( bCallOutSet )
921 Out_SfxItemSet( rFmt.GetAttrSet(), bPapFmt, bChpFmt,
922 i18n::ScriptType::LATIN);
923 pOutFmtNode = pOldMod;
926 bool SwWW8Writer::HasRefToObject(USHORT nTyp, const String* pNm, USHORT nSeqNo)
928 bool bFnd = false;
929 const SwTxtNode* pNd;
930 SwClientIter aIter( *pDoc->GetSysFldType( RES_GETREFFLD ));
931 for( SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE( SwFmtFld ));
932 pFld && !bFnd; pFld = (SwFmtFld*)aIter.Next() )
933 if( pFld->GetTxtFld() && nTyp == pFld->GetFld()->GetSubType() &&
934 0 != ( pNd = pFld->GetTxtFld()->GetpTxtNode() ) &&
935 pNd->GetNodes().IsDocNodes() )
937 const SwGetRefField& rRFld = *(SwGetRefField*)pFld->GetFld();
938 switch( nTyp )
940 case REF_BOOKMARK:
941 case REF_SETREFATTR:
942 bFnd = (*pNm == rRFld.GetSetRefName()) ? true : false;
943 break;
944 case REF_FOOTNOTE:
945 case REF_ENDNOTE:
946 bFnd = (nSeqNo == rRFld.GetSeqNo()) ? true : false;
947 break;
948 case REF_SEQUENCEFLD: break; // ???
949 case REF_OUTLINE: break; // ???
953 return bFnd;
956 String SwWW8Writer::GetBookmarkName( USHORT nTyp, const String* pNm,
957 USHORT nSeqNo )
959 String sRet;
960 switch( nTyp )
962 case REF_SETREFATTR:
963 sRet.APPEND_CONST_ASC( "Ref_" );
964 sRet += *pNm;
965 break;
966 case REF_SEQUENCEFLD:
967 break; // ???
968 case REF_BOOKMARK:
969 sRet = *pNm;
970 break;
971 case REF_OUTLINE:
972 break; // ???
973 case REF_FOOTNOTE:
974 sRet.APPEND_CONST_ASC( "_RefF" );
975 sRet += String::CreateFromInt32( nSeqNo );
976 break;
977 case REF_ENDNOTE:
978 sRet.APPEND_CONST_ASC( "_RefE" );
979 sRet += String::CreateFromInt32( nSeqNo );
980 break;
982 // --> OD 2005-06-08 #i43956# - encode bookmark accordingly
983 return BookmarkToWord( sRet );
984 // <--
987 //-----------------------------------------------------------------------
988 /* \f */
989 /* File CHRATR.HXX: */
991 static Writer& OutWW8_SwBoldUSW(Writer& rWrt, BYTE nId, bool bVal)
993 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
994 if( rWrtWW8.bWrtWW8 )
995 rWrtWW8.InsUInt16(8 == nId ? 0x2a53 : 0x0835 + nId);
996 else if (8 == nId )
997 return rWrt; // das Attribut gibt es im WW6 nicht
998 else
999 rWrtWW8.pO->Insert( 85 + nId, rWrtWW8.pO->Count() );
1000 rWrtWW8.pO->Insert( bVal ? 1 : 0, rWrtWW8.pO->Count() );
1001 return rWrt;
1004 static Writer& OutWW8_SwBoldBiDiUSW(Writer& rWrt, BYTE nId, bool bVal)
1006 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1007 ASSERT(nId <= 1, "out of range");
1008 if (!rWrtWW8.bWrtWW8 || nId > 1)
1009 return rWrt;
1011 rWrtWW8.InsUInt16(0x085C + nId);
1012 rWrtWW8.pO->Insert(bVal ? 1 : 0, rWrtWW8.pO->Count());
1013 return rWrt;
1016 static Writer& OutWW8_SwFont( Writer& rWrt, const SfxPoolItem& rHt )
1018 const SvxFontItem& rAttr = (const SvxFontItem&)rHt;
1019 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1020 USHORT nFontID= rWrtWW8.GetId(rAttr);
1022 if( rWrtWW8.bWrtWW8 )
1024 rWrtWW8.InsUInt16( 0x4a4f );
1025 rWrtWW8.InsUInt16( nFontID );
1026 rWrtWW8.InsUInt16( 0x4a51 );
1028 else
1029 rWrtWW8.pO->Insert( 93, rWrtWW8.pO->Count() );
1030 rWrtWW8.InsUInt16( nFontID );
1031 return rWrt;
1034 static Writer& OutWW8_SwCTLFont(Writer& rWrt, const SfxPoolItem& rHt)
1036 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1037 if (rWrtWW8.bWrtWW8)
1039 rWrtWW8.InsUInt16(0x4A5E);
1040 rWrtWW8.InsUInt16(rWrtWW8.GetId((const SvxFontItem&)rHt));
1042 return rWrt;
1045 static Writer& OutWW8_SwCJKFont( Writer& rWrt, const SfxPoolItem& rHt )
1047 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1048 if( rWrtWW8.bWrtWW8 )
1050 rWrtWW8.InsUInt16( 0x4a50 );
1051 rWrtWW8.InsUInt16(rWrtWW8.GetId((const SvxFontItem&)rHt));
1053 return rWrt;
1056 static Writer& OutWW8_SwBiDiWeight( Writer& rWrt, const SfxPoolItem& rHt )
1058 //Can only export in 8+, in 7- export as normal varient and expect that
1059 //upperlevel code has blocked exporting clobbering attributes
1060 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1061 if (rWrtWW8.bWrtWW8)
1063 OutWW8_SwBoldBiDiUSW(rWrt, 0,
1064 WEIGHT_BOLD == ((const SvxWeightItem&)rHt).GetWeight());
1066 else
1068 OutWW8_SwBoldUSW(rWrt, 0,
1069 WEIGHT_BOLD == ((const SvxWeightItem&)rHt).GetWeight());
1071 return rWrt;
1074 static Writer& OutWW8_SwBiDiPosture( Writer& rWrt, const SfxPoolItem& rHt )
1076 //Can only export in 8+, in 7- export as normal varient and expect that
1077 //upperlevel code has blocked exporting clobbering attributes
1078 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1079 if (rWrtWW8.bWrtWW8)
1081 OutWW8_SwBoldBiDiUSW( rWrt, 1,
1082 ITALIC_NONE != ((const SvxPostureItem&)rHt).GetPosture() );
1084 else
1086 OutWW8_SwBoldUSW( rWrt, 1,
1087 ITALIC_NONE != ((const SvxPostureItem&)rHt).GetPosture() );
1089 return rWrt;
1092 static Writer& OutWW8_SwPosture( Writer& rWrt, const SfxPoolItem& rHt )
1094 return OutWW8_SwBoldUSW( rWrt, 1,
1095 ITALIC_NONE != ((const SvxPostureItem&)rHt).GetPosture() );
1098 static Writer& OutWW8_SwWeight( Writer& rWrt, const SfxPoolItem& rHt )
1100 return OutWW8_SwBoldUSW( rWrt, 0,
1101 WEIGHT_BOLD == ((const SvxWeightItem&)rHt).GetWeight() );
1104 // Shadowed und Contour gibts in WW-UI nicht. JP: ??
1105 static Writer& OutWW8_SwContour( Writer& rWrt, const SfxPoolItem& rHt )
1107 return OutWW8_SwBoldUSW(rWrt, 3,
1108 ((const SvxContourItem&)rHt).GetValue() ? true : false);
1111 static Writer& OutWW8_SwShadow( Writer& rWrt, const SfxPoolItem& rHt )
1113 return OutWW8_SwBoldUSW(rWrt, 4,
1114 ((const SvxShadowedItem&)rHt).GetValue() ? true : false);
1117 static Writer& OutWW8_SwKerning( Writer& rWrt, const SfxPoolItem& rHt )
1119 const SvxKerningItem& rAttr = (const SvxKerningItem&)rHt;
1120 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1121 if( rWrtWW8.bWrtWW8 )
1122 rWrtWW8.InsUInt16( 0x8840 );
1123 else
1124 rWrtWW8.pO->Insert( 96, rWrtWW8.pO->Count() );
1125 rWrtWW8.InsUInt16( rAttr.GetValue() );
1126 return rWrt;
1129 static Writer& OutWW8_SvxAutoKern( Writer& rWrt, const SfxPoolItem& rHt )
1131 const SvxAutoKernItem& rAttr = (const SvxAutoKernItem&)rHt;
1132 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1133 if( rWrtWW8.bWrtWW8 )
1134 rWrtWW8.InsUInt16( 0x484B );
1135 else
1136 rWrtWW8.pO->Insert( 107, rWrtWW8.pO->Count() );
1137 rWrtWW8.InsUInt16( rAttr.GetValue() ? 1 : 0 );
1138 return rWrt;
1141 static Writer& OutWW8_SwAnimatedText( Writer& rWrt, const SfxPoolItem& rHt )
1143 const SvxBlinkItem& rAttr = (const SvxBlinkItem&)rHt;
1144 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1145 if( rWrtWW8.bWrtWW8 )
1147 rWrtWW8.InsUInt16( 0x2859 );
1148 // At the moment the only animated text effect we support is blinking
1149 rWrtWW8.InsUInt16( rAttr.GetValue() ? 2 : 0 );
1151 return rWrt;
1155 static Writer& OutWW8_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt )
1157 FontStrikeout eSt = ((const SvxCrossedOutItem&)rHt).GetStrikeout();
1158 if( STRIKEOUT_DOUBLE == eSt )
1159 return OutWW8_SwBoldUSW(rWrt, 8, true);
1160 if( STRIKEOUT_NONE != eSt )
1161 return OutWW8_SwBoldUSW(rWrt, 2, true);
1163 // dann auch beide ausschalten!
1164 OutWW8_SwBoldUSW(rWrt, 8, false);
1165 return OutWW8_SwBoldUSW(rWrt, 2, false);
1168 static Writer& OutWW8_SwCaseMap( Writer& rWrt, const SfxPoolItem& rHt )
1170 USHORT eSt = ((const SvxCaseMapItem&)rHt).GetValue();
1171 switch (eSt)
1173 case SVX_CASEMAP_KAPITAELCHEN:
1174 return OutWW8_SwBoldUSW(rWrt, 5, true);
1175 case SVX_CASEMAP_VERSALIEN:
1176 return OutWW8_SwBoldUSW(rWrt, 6, true);
1177 case SVX_CASEMAP_TITEL:
1178 //NO such feature in word
1179 break;
1180 default:
1181 // dann auch beide ausschalten!
1182 OutWW8_SwBoldUSW(rWrt, 5, false);
1183 return OutWW8_SwBoldUSW(rWrt, 6, false);
1185 return rWrt;
1188 static Writer& OutWW8_SvxCharHidden(Writer& rWrt, const SfxPoolItem& rHt )
1190 OutWW8_SwBoldUSW(rWrt, 7, (item_cast<SvxCharHiddenItem>(rHt)).GetValue());
1191 return rWrt;
1194 static Writer& OutWW8_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt )
1196 const SvxUnderlineItem& rAttr = (const SvxUnderlineItem&)rHt;
1197 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1198 if( rWrtWW8.bWrtWW8 )
1199 rWrtWW8.InsUInt16( 0x2A3E );
1200 else
1201 rWrtWW8.pO->Insert( 94, rWrtWW8.pO->Count() );
1203 const SfxPoolItem* pItem = ((SwWW8Writer&)rWrt).HasItem(
1204 RES_CHRATR_WORDLINEMODE );
1205 bool bWord = false;
1206 if (pItem)
1207 bWord = ((const SvxWordLineModeItem*)pItem)->GetValue() ? true : false;
1209 // WW95 - parameters: 0 = none, 1 = single, 2 = by Word,
1210 // 3 = double, 4 = dotted, 5 = hidden
1211 // WW97 - additional parameters:
1212 // 6 = thick, 7 = dash, 8 = dot(not used)
1213 // 9 = dotdash 10 = dotdotdash, 11 = wave
1214 BYTE b = 0;
1215 switch (rAttr.GetLineStyle())
1217 case UNDERLINE_SINGLE:
1218 b = ( bWord ) ? 2 : 1;
1219 break;
1220 case UNDERLINE_BOLD:
1221 b = rWrtWW8.bWrtWW8 ? 6 : 1;
1222 break;
1223 case UNDERLINE_DOUBLE:
1224 b = 3;
1225 break;
1226 case UNDERLINE_DOTTED:
1227 b = 4;
1228 break;
1229 case UNDERLINE_DASH:
1230 b = rWrtWW8.bWrtWW8 ? 7 : 4;
1231 break;
1232 case UNDERLINE_DASHDOT:
1233 b = rWrtWW8.bWrtWW8 ? 9 : 4;
1234 break;
1235 case UNDERLINE_DASHDOTDOT:
1236 b = rWrtWW8.bWrtWW8 ? 10 : 4;
1237 break;
1238 case UNDERLINE_WAVE:
1239 b = rWrtWW8.bWrtWW8 ? 11 : 3;
1240 break;
1241 // ------------ new in WW2000 -------------------------------------
1242 case UNDERLINE_BOLDDOTTED:
1243 b = rWrtWW8.bWrtWW8 ? 20 : 4;
1244 break;
1245 case UNDERLINE_BOLDDASH:
1246 b = rWrtWW8.bWrtWW8 ? 23 : 4;
1247 break;
1248 case UNDERLINE_LONGDASH:
1249 b = rWrtWW8.bWrtWW8 ? 39 : 4;
1250 break;
1251 case UNDERLINE_BOLDLONGDASH:
1252 b = rWrtWW8.bWrtWW8 ? 55 : 4;
1253 break;
1254 case UNDERLINE_BOLDDASHDOT:
1255 b = rWrtWW8.bWrtWW8 ? 25 : 4;
1256 break;
1257 case UNDERLINE_BOLDDASHDOTDOT:
1258 b = rWrtWW8.bWrtWW8 ? 26 : 4;
1259 break;
1260 case UNDERLINE_BOLDWAVE:
1261 b = rWrtWW8.bWrtWW8 ? 27 : 3;
1262 break;
1263 case UNDERLINE_DOUBLEWAVE:
1264 b = rWrtWW8.bWrtWW8 ? 43 : 3;
1265 break;
1266 case UNDERLINE_NONE:
1267 b = 0;
1268 break;
1269 default:
1270 ASSERT(rAttr.GetLineStyle() == UNDERLINE_NONE, "Unhandled underline type");
1271 break;
1274 rWrtWW8.pO->Insert(b, rWrtWW8.pO->Count());
1275 return rWrt;
1278 static Writer& OutWW8_SwLanguage( Writer& rWrt, const SfxPoolItem& rHt )
1280 USHORT nId = 0;
1281 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1282 if (rWrtWW8.bWrtWW8)
1284 switch (rHt.Which())
1286 case RES_CHRATR_LANGUAGE:
1287 nId = 0x486D;
1288 break;
1289 case RES_CHRATR_CJK_LANGUAGE:
1290 nId = 0x486E;
1291 break;
1292 case RES_CHRATR_CTL_LANGUAGE:
1293 nId = 0x485F;
1294 break;
1297 else
1298 nId = 97;
1300 if (nId)
1302 if (rWrtWW8.bWrtWW8) // use sprmCRgLid0 rather than sprmCLid
1303 rWrtWW8.InsUInt16(nId);
1304 else
1305 rWrtWW8.pO->Insert((BYTE)nId, rWrtWW8.pO->Count());
1306 rWrtWW8.InsUInt16(((const SvxLanguageItem&)rHt).GetLanguage());
1308 //unknown as to exactly why, but this seems to shadow the other
1309 //paramater in word 2000 and without it spellchecking doesn't work
1310 if (nId == 0x486D)
1312 rWrtWW8.InsUInt16(0x4873);
1313 rWrtWW8.InsUInt16(((const SvxLanguageItem&)rHt).GetLanguage());
1315 else if (nId == 0x485F)
1317 rWrtWW8.InsUInt16(0x4874);
1318 rWrtWW8.InsUInt16(((const SvxLanguageItem&)rHt).GetLanguage());
1322 return rWrt;
1325 static Writer& OutWW8_SwEscapement( Writer& rWrt, const SfxPoolItem& rHt )
1327 const SvxEscapementItem& rAttr = (const SvxEscapementItem&)rHt;
1328 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1330 BYTE b = 0xFF;
1331 short nEsc = rAttr.GetEsc(), nProp = rAttr.GetProp();
1332 if( !nEsc )
1334 b = 0;
1335 nEsc = 0;
1336 nProp = 100;
1338 else if( DFLT_ESC_PROP == nProp )
1340 if( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
1341 b = 2;
1342 else if( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
1343 b = 1;
1346 if( 0xFF != b )
1348 if( rWrtWW8.bWrtWW8 )
1349 rWrtWW8.InsUInt16( 0x2A48 );
1350 else
1351 rWrtWW8.pO->Insert( 104, rWrtWW8.pO->Count() );
1352 rWrtWW8.pO->Insert( b, rWrtWW8.pO->Count() );
1355 if( 0 == b || 0xFF == b )
1357 long nHeight = ((SvxFontHeightItem&)rWrtWW8.GetItem(
1358 RES_CHRATR_FONTSIZE )).GetHeight();
1359 if( rWrtWW8.bWrtWW8 )
1360 rWrtWW8.InsUInt16( 0x4845 );
1361 else
1362 rWrtWW8.pO->Insert( 101, rWrtWW8.pO->Count() );
1363 rWrtWW8.InsUInt16( (short)(( nHeight * nEsc + 500 ) / 1000 ));
1365 if( 100 != nProp || !b )
1367 if( rWrtWW8.bWrtWW8 )
1368 rWrtWW8.InsUInt16( 0x4A43 );
1369 else
1370 rWrtWW8.pO->Insert( 99, rWrtWW8.pO->Count() );
1371 rWrtWW8.InsUInt16(
1372 msword_cast<sal_uInt16>((nHeight * nProp + 500 ) / 1000));
1376 return rWrt;
1379 static Writer& OutWW8_SwSize( Writer& rWrt, const SfxPoolItem& rHt )
1381 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1382 USHORT nId = 0;
1383 if (rWrtWW8.bWrtWW8)
1385 switch (rHt.Which())
1387 case RES_CHRATR_FONTSIZE:
1388 case RES_CHRATR_CJK_FONTSIZE:
1389 nId = 0x4A43;
1390 break;
1391 case RES_CHRATR_CTL_FONTSIZE:
1392 nId = 0x4A61;
1393 break;
1396 else
1397 nId = 99;
1399 if( nId )
1401 if( rWrtWW8.bWrtWW8 )
1402 rWrtWW8.InsUInt16( nId );
1403 else
1404 rWrtWW8.pO->Insert( (BYTE)nId, rWrtWW8.pO->Count() );
1406 const SvxFontHeightItem& rAttr = (const SvxFontHeightItem&)rHt;
1407 rWrtWW8.InsUInt16( (UINT16)(( rAttr.GetHeight() + 5 ) / 10 ) );
1409 return rWrt;
1412 static Writer& OutWW8_ScaleWidth( Writer& rWrt, const SfxPoolItem& rHt )
1414 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1415 if( rWrtWW8.bWrtWW8 )
1417 rWrtWW8.InsUInt16( 0x4852 );
1418 rWrtWW8.InsUInt16( ((SvxCharScaleWidthItem&)rHt).GetValue() );
1420 return rWrt;
1423 static Writer& OutWW8_Relief( Writer& rWrt, const SfxPoolItem& rHt )
1425 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1426 if( rWrtWW8.bWrtWW8 )
1428 const SvxCharReliefItem& rAttr = (const SvxCharReliefItem&)rHt;
1429 USHORT nId;
1430 switch ( rAttr.GetValue() )
1432 case RELIEF_EMBOSSED: nId = 0x858; break;
1433 case RELIEF_ENGRAVED: nId = 0x854; break;
1434 default: nId = 0; break;
1437 if( nId )
1439 rWrtWW8.InsUInt16( nId );
1440 rWrtWW8.pO->Insert( (BYTE)0x81, rWrtWW8.pO->Count() );
1442 else
1444 // switch both flags off
1445 rWrtWW8.InsUInt16( 0x858 );
1446 rWrtWW8.pO->Insert( (BYTE)0x0, rWrtWW8.pO->Count() );
1447 rWrtWW8.InsUInt16( 0x854 );
1448 rWrtWW8.pO->Insert( (BYTE)0x0, rWrtWW8.pO->Count() );
1451 return rWrt;
1455 static Writer& OutWW8_CharRotate( Writer& rWrt, const SfxPoolItem& rHt )
1457 // #i28331# - check that a Value is set
1458 if((static_cast<const SvxCharRotateItem&>(rHt)).GetValue())
1460 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1461 if( rWrtWW8.bWrtWW8 && !rWrtWW8.bIsInTable )
1463 // #i36867 In word the text in a table is rotated via the TC or 0x7629
1464 // This means you can only rotate all or none of the text adding 0xCA78
1465 // here corrupts the table, hence !rWrtWW8.bIsInTable
1466 const SvxCharRotateItem& rAttr = (const SvxCharRotateItem&)rHt;
1468 rWrtWW8.InsUInt16( 0xCA78 );
1469 rWrtWW8.pO->Insert( (BYTE)0x06, rWrtWW8.pO->Count() ); //len 6
1470 rWrtWW8.pO->Insert( (BYTE)0x01, rWrtWW8.pO->Count() );
1472 rWrtWW8.InsUInt16( rAttr.IsFitToLine() ? 1 : 0 );
1473 static const BYTE aZeroArr[ 3 ] = { 0, 0, 0 };
1474 rWrtWW8.pO->Insert( aZeroArr, 3, rWrtWW8.pO->Count() );
1477 return rWrt;
1481 static Writer& OutWW8_EmphasisMark( Writer& rWrt, const SfxPoolItem& rHt )
1483 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1484 if( rWrtWW8.bWrtWW8 )
1486 BYTE nVal;
1487 switch ( ((const SvxEmphasisMarkItem&)rHt).GetValue() )
1489 case EMPHASISMARK_NONE: nVal = 0; break;
1490 case EMPHASISMARK_SIDE_DOTS: nVal = 2; break;
1491 case EMPHASISMARK_CIRCLE_ABOVE: nVal = 3; break;
1492 case EMPHASISMARK_DOTS_BELOW: nVal = 4; break;
1493 // case 1:
1494 default: nVal = 1; break;
1497 rWrtWW8.InsUInt16( 0x2A34 );
1498 rWrtWW8.pO->Insert( nVal, rWrtWW8.pO->Count() );
1500 return rWrt;
1504 // TransCol uebersetzt SW-Farben in WW. Heraus kommt die bei WW fuer
1505 // Text- und Hintergrundfarbe benutzte Codierung.
1506 // Gibt es keine direkte Entsprechung, dann wird versucht, eine moeglichst
1507 // aehnliche WW-Farbe zu finden.
1508 // return: 5-Bit-Wert ( 0..16 )
1509 BYTE SwWW8Writer::TransCol( const Color& rCol )
1511 BYTE nCol = 0; // ->Auto
1512 switch( rCol.GetColor() )
1514 case COL_BLACK: nCol = 1; break;
1515 case COL_BLUE: nCol = 9; break;
1516 case COL_GREEN: nCol = 11; break;
1517 case COL_CYAN: nCol = 10; break;
1518 case COL_RED: nCol = 13; break;
1519 case COL_MAGENTA: nCol = 12; break;
1520 case COL_BROWN: nCol = 14; break;
1521 case COL_GRAY: nCol = 15; break;
1522 case COL_LIGHTGRAY: nCol = 16; break;
1523 case COL_LIGHTBLUE: nCol = 2; break;
1524 case COL_LIGHTGREEN: nCol = 4; break;
1525 case COL_LIGHTCYAN: nCol = 3; break;
1526 case COL_LIGHTRED: nCol = 6; break;
1527 case COL_LIGHTMAGENTA: nCol = 5; break;
1528 case COL_YELLOW: nCol = 7; break;
1529 case COL_WHITE: nCol = 8; break;
1530 case COL_AUTO: nCol = 0; break;
1532 default:
1533 if( !pBmpPal )
1535 pBmpPal = new BitmapPalette( 16 );
1536 static const ColorData aColArr[ 16 ] = {
1537 COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
1538 COL_LIGHTMAGENTA,COL_LIGHTRED, COL_YELLOW, COL_WHITE,
1539 COL_BLUE, COL_CYAN, COL_GREEN, COL_MAGENTA,
1540 COL_RED, COL_BROWN, COL_GRAY, COL_LIGHTGRAY
1543 for( USHORT i = 0; i < 16; ++i )
1544 pBmpPal->operator[]( i ) = Color( aColArr[ i ] );
1546 nCol = static_cast< BYTE >(pBmpPal->GetBestIndex( rCol ) + 1);
1547 break;
1549 return nCol;
1552 // TransBrush uebersetzt SW-Brushes in WW. Heraus kommt WW8_SHD.
1553 // Nicht-Standardfarben des SW werden noch nicht in die
1554 // Misch-Werte ( 0 .. 95% ) vom WW uebersetzt.
1555 // Return: Echte Brush ( nicht transparent )
1556 // auch bei Transparent wird z.B. fuer Tabellen eine transparente Brush
1557 // geliefert
1558 bool SwWW8Writer::TransBrush(const Color& rCol, WW8_SHD& rShd)
1560 if( rCol.GetTransparency() )
1561 rShd = WW8_SHD(); // alles Nullen : transparent
1562 else
1564 rShd.SetFore( 8);
1565 rShd.SetBack( TransCol( rCol ) );
1566 rShd.SetStyle( bWrtWW8, 0 );
1568 return !rCol.GetTransparency();
1571 sal_uInt32 SuitableBGColor(sal_uInt32 nIn)
1573 if (nIn == COL_AUTO)
1574 return 0xFF000000;
1575 return wwUtility::RGBToBGR(nIn);
1578 static Writer& OutWW8_SwColor( Writer& rWrt, const SfxPoolItem& rHt )
1580 const SvxColorItem& rAttr = (const SvxColorItem&)rHt;
1581 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1582 if (rWrtWW8.bWrtWW8)
1583 rWrtWW8.InsUInt16(0x2A42);
1584 else
1585 rWrtWW8.pO->Insert(98, rWrtWW8.pO->Count());
1587 BYTE nColour = rWrtWW8.TransCol(rAttr.GetValue());
1588 rWrtWW8.pO->Insert(nColour, rWrtWW8.pO->Count());
1590 if (rWrtWW8.bWrtWW8 && nColour)
1592 rWrtWW8.InsUInt16(0x6870);
1593 rWrtWW8.InsUInt32(wwUtility::RGBToBGR(rAttr.GetValue().GetColor()));
1595 return rWrt;
1598 static Writer& OutWW8_SwFmtCharBackground( Writer& rWrt, const SfxPoolItem& rHt )
1600 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
1602 if( rWW8Wrt.bWrtWW8 ) // nur WW8 kann ZeichenHintergrund
1604 const SvxBrushItem& rBack = (const SvxBrushItem&)rHt;
1605 WW8_SHD aSHD;
1607 rWW8Wrt.TransBrush(rBack.GetColor(), aSHD);
1608 // sprmCShd
1609 rWW8Wrt.InsUInt16( 0x4866 );
1610 rWW8Wrt.InsUInt16( aSHD.GetValue() );
1612 //Quite a few unknowns, some might be transparency or something
1613 //of that nature...
1614 rWW8Wrt.InsUInt16(0xCA71);
1615 rWW8Wrt.pO->Insert(10, rWW8Wrt.pO->Count());
1616 rWW8Wrt.InsUInt32(0xFF000000);
1617 rWW8Wrt.InsUInt32(SuitableBGColor(rBack.GetColor().GetColor()));
1618 rWW8Wrt.InsUInt16(0x0000);
1620 return rWrt;
1623 static Writer& OutSwFmtINetFmt( Writer& rWrt, const SfxPoolItem& rHt )
1625 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
1626 const SwFmtINetFmt& rINet = (SwFmtINetFmt&)rHt;
1628 if( rINet.GetValue().Len() )
1630 USHORT nId;
1631 const String& rStr = rINet.GetINetFmt();
1632 if( rStr.Len() )
1633 nId = rINet.GetINetFmtId();
1634 else
1635 nId = RES_POOLCHR_INET_NORMAL;
1637 const SwCharFmt* pFmt = IsPoolUserFmt( nId )
1638 ? rWrt.pDoc->FindCharFmtByName( rStr )
1639 : rWrt.pDoc->GetCharFmtFromPool( nId );
1641 if( rWrtWW8.bWrtWW8 )
1642 rWrtWW8.InsUInt16( 0x4A30 );
1643 else
1644 rWrtWW8.pO->Insert( 80, rWrtWW8.pO->Count() );
1646 rWrtWW8.InsUInt16( rWrtWW8.GetId( *pFmt ) );
1648 return rWrt;
1651 // --> OD 2005-06-08 #i43956# - add optional parameter <pLinkStr>
1652 // It's needed to write the hyperlink data for a certain cross-reference
1653 // - it contains the name of the link target, which is a bookmark.
1654 // --> OD 2008-08-14 #158418# - add optional parameter <bIncludeEmptyPicLocation>
1655 // It is needed to write an empty picture location for page number field separators
1656 static void InsertSpecialChar( SwWW8Writer& rWrt, BYTE c,
1657 String* pLinkStr = 0L,
1658 bool bIncludeEmptyPicLocation = false )
1660 WW8Bytes aItems;
1661 rWrt.GetCurrentItems(aItems);
1663 if (c == 0x13)
1664 rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell());
1665 else
1666 rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.Count(),
1667 aItems.GetData());
1669 rWrt.WriteChar(c);
1671 // --> OD 2008-08-14 #158418#
1672 // store empty sprmCPicLocation for field separator
1673 if ( bIncludeEmptyPicLocation &&
1674 ( c == 0x13 || c == 0x14 || c == 0x15 ) )
1676 SwWW8Writer::InsUInt16( aItems, 0x6a03 );
1677 SwWW8Writer::InsUInt32( aItems, 0x00000000 );
1679 // <--
1681 // --> OD 2005-06-08 #i43956# - write hyperlink data and attributes
1682 if ( rWrt.bWrtWW8 && c == 0x01 && pLinkStr )
1684 // write hyperlink data to data stream
1685 SvStream& rStrm = *rWrt.pDataStrm;
1686 // position of hyperlink data
1687 const UINT32 nLinkPosInDataStrm = rStrm.Tell();
1688 // write empty header
1689 const UINT16 nEmptyHdrLen = 0x44;
1690 BYTE aEmptyHeader[ nEmptyHdrLen ] = { 0 };
1691 aEmptyHeader[ 4 ] = 0x44;
1692 rStrm.Write( aEmptyHeader, nEmptyHdrLen );
1693 // writer fixed header
1694 const UINT16 nFixHdrLen = 0x19;
1695 BYTE aFixHeader[ nFixHdrLen ] =
1697 0x08, 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE,
1698 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9,
1699 0x0B, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
1700 0x00,
1702 rStrm.Write( aFixHeader, nFixHdrLen );
1703 // write reference string including length+1
1704 UINT32 nStrLen( pLinkStr->Len() + 1 );
1705 SwWW8Writer::WriteLong( rStrm, nStrLen );
1706 SwWW8Writer::WriteString16( rStrm, *(pLinkStr), false );
1707 // write additional two NULL Bytes
1708 SwWW8Writer::WriteLong( rStrm, 0 );
1709 // write length of hyperlink data
1710 const UINT32 nCurrPos = rStrm.Tell();
1711 rStrm.Seek( nLinkPosInDataStrm );
1712 SVBT32 nLen;
1713 UInt32ToSVBT32( nCurrPos - nLinkPosInDataStrm, nLen );
1714 rStrm.Write( nLen, 4 );
1715 rStrm.Seek( nCurrPos );
1717 // write attributes of hyperlink character 0x01
1718 SwWW8Writer::InsUInt16( aItems, 0x0802 ); //sprmCFFldVanish
1719 aItems.Insert( (BYTE)0x81, aItems.Count() );
1720 SwWW8Writer::InsUInt16( aItems, 0x6a03 );
1721 SwWW8Writer::InsUInt32( aItems, nLinkPosInDataStrm );
1722 SwWW8Writer::InsUInt16( aItems, 0x0806 );
1723 aItems.Insert( (BYTE)0x01, aItems.Count() );
1726 //Technically we should probably Remove all attribs
1727 //here for the 0x13, 0x14, 0x15, but our import
1728 //is slightly lacking
1729 //aItems.Remove(0, aItems.Count());
1730 // fSpec-Attribute true
1731 if( rWrt.bWrtWW8 )
1733 SwWW8Writer::InsUInt16( aItems, 0x855 ); //sprmCFSpec
1734 aItems.Insert( 1, aItems.Count() );
1736 else
1738 aItems.Insert( 117, aItems.Count() ); //sprmCFSpec
1739 aItems.Insert( 1, aItems.Count() );
1742 rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.Count(),
1743 aItems.GetData());
1746 String lcl_GetExpandedField(const SwField &rFld)
1748 String sRet(rFld.Expand());
1750 //replace LF 0x0A with VT 0x0B
1751 sRet.SearchAndReplaceAll(0x0A, 0x0B);
1753 return sRet;
1756 WW8_WrPlcFld* SwWW8Writer::CurrentFieldPlc() const
1758 WW8_WrPlcFld* pFldP = NULL;
1759 switch (nTxtTyp)
1761 case TXT_MAINTEXT:
1762 pFldP = pFldMain;
1763 break;
1764 case TXT_HDFT:
1765 pFldP = pFldHdFt;
1766 break;
1767 case TXT_FTN:
1768 pFldP = pFldFtn;
1769 break;
1770 case TXT_EDN:
1771 pFldP = pFldEdn;
1772 break;
1773 case TXT_ATN:
1774 pFldP = pFldAtn;
1775 break;
1776 case TXT_TXTBOX:
1777 pFldP = pFldTxtBxs;
1778 break;
1779 case TXT_HFTXTBOX:
1780 pFldP = pFldHFTxtBxs;
1781 break;
1782 default:
1783 ASSERT( !this, "was ist das fuer ein SubDoc-Type?" );
1785 return pFldP;
1788 void SwWW8Writer::OutField(const SwField* pFld, ww::eField eFldType,
1789 const String& rFldCmd, BYTE nMode)
1791 bool bUnicode = IsUnicode();
1792 WW8_WrPlcFld* pFldP = CurrentFieldPlc();
1794 // --> OD 2008-08-14 #158418#
1795 const bool bIncludeEmptyPicLocation = ( eFldType == ww::ePAGE );
1796 // <--
1797 if (WRITEFIELD_START & nMode)
1799 BYTE aFld13[2] = { 0x13, 0x00 }; // will change
1800 //#i3958#, Needed to make this field work correctly in Word 2000
1801 if (eFldType == ww::eSHAPE)
1802 aFld13[0] |= 0x80;
1803 aFld13[1] = static_cast< BYTE >(eFldType); // Typ nachtragen
1804 pFldP->Append( Fc2Cp( Strm().Tell() ), aFld13 );
1805 // --> OD 2008-08-14 #158418#
1806 InsertSpecialChar( *this, 0x13, 0, bIncludeEmptyPicLocation );
1807 // <--
1809 if (WRITEFIELD_CMD_START & nMode)
1811 if (bUnicode)
1812 SwWW8Writer::WriteString16(Strm(), rFldCmd, false);
1813 else
1815 SwWW8Writer::WriteString8(Strm(), rFldCmd, false,
1816 RTL_TEXTENCODING_MS_1252);
1818 // --> OD 2005-06-08 #i43956# - write hyperlink character including
1819 // attributes and corresponding binary data for certain reference fields.
1820 bool bHandleBookmark = false;
1822 if (pFld)
1824 if (pFld->GetTyp()->Which() == RES_GETREFFLD &&
1825 ( eFldType == ww::ePAGEREF || eFldType == ww::eREF ||
1826 eFldType == ww::eNOTEREF || eFldType == ww::eFOOTREF ))
1827 bHandleBookmark = true;
1829 #if 0
1830 if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
1831 eFldType == ww::eFORMTEXT)
1832 bHandleBookmark = true;
1833 #endif
1836 if ( bHandleBookmark )
1838 // retrieve reference destionation - the name of the bookmark
1839 String aLinkStr;
1840 const USHORT nSubType = pFld->GetSubType();
1841 const SwGetRefField& rRFld = *(static_cast<const SwGetRefField*>(pFld));
1842 if ( nSubType == REF_SETREFATTR ||
1843 nSubType == REF_BOOKMARK )
1845 aLinkStr = GetBookmarkName( nSubType, &rRFld.GetSetRefName(), 0 );
1847 else if ( nSubType == REF_FOOTNOTE ||
1848 nSubType == REF_ENDNOTE )
1850 aLinkStr = GetBookmarkName( nSubType, 0, rRFld.GetSeqNo() );
1852 else if ( nSubType == REF_SEQUENCEFLD )
1854 aLinkStr = pFld->GetPar2();
1856 // insert hyperlink character including attributes and data.
1857 InsertSpecialChar( *this, 0x01, &aLinkStr );
1859 // <--
1861 if (WRITEFIELD_CMD_END & nMode)
1863 static const BYTE aFld14[2] = { 0x14, 0xff };
1864 pFldP->Append( Fc2Cp( Strm().Tell() ), aFld14 );
1865 pFldP->ResultAdded();
1866 // --> OD 2008-08-14 #158418#
1867 InsertSpecialChar( *this, 0x14, 0, bIncludeEmptyPicLocation );
1868 // <--
1870 if (WRITEFIELD_END & nMode)
1872 String sOut;
1873 if( pFld )
1874 sOut = lcl_GetExpandedField(*pFld);
1875 else
1876 sOut = rFldCmd;
1877 if( sOut.Len() )
1879 if( bUnicode )
1880 SwWW8Writer::WriteString16(Strm(), sOut, false);
1881 else
1883 SwWW8Writer::WriteString8(Strm(), sOut, false,
1884 RTL_TEXTENCODING_MS_1252);
1887 if (pFld)
1889 if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
1890 eFldType == ww::eFORMTEXT)
1892 BYTE aArr[12];
1893 BYTE *pArr = aArr;
1895 if( bWrtWW8 )
1897 Set_UInt16(pArr, 0x6a03); //sprmCPicLocation
1898 Set_UInt32(pArr, 0x0);
1900 Set_UInt16( pArr, 0x855 );//sprmCFSpec
1901 Set_UInt8( pArr, 1 );
1903 Set_UInt16( pArr, 0x875 );//sprmCFNoProof
1904 Set_UInt8(pArr, 1);
1906 else
1908 Set_UInt8(pArr, 0x68); //sprmCPicLocation
1909 Set_UInt32(pArr, 0x0);
1911 Set_UInt8( pArr, 117 ); //sprmCFSpec
1912 Set_UInt8( pArr, 1 );
1914 pChpPlc->AppendFkpEntry( pStrm->Tell(), static_cast< short >(pArr - aArr), aArr );
1919 if (WRITEFIELD_CLOSE & nMode)
1921 BYTE aFld15[2] = { 0x15, 0x80 };
1923 if (pFld)
1925 if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
1926 eFldType == ww::eFORMTEXT)
1928 USHORT nSubType = pFld->GetSubType();
1930 if (nSubType == REF_SEQUENCEFLD)
1931 aFld15[0] |= (0x4 << 5);
1935 pFldP->Append( Fc2Cp( Strm().Tell() ), aFld15 );
1936 // --> OD 2008-08-14 #158418#
1937 InsertSpecialChar( *this, 0x15, 0, bIncludeEmptyPicLocation );
1938 // <--
1942 void SwWW8Writer::StartCommentOutput(const String& rName)
1944 String sStr(FieldString(ww::eQUOTE));
1945 sStr.APPEND_CONST_ASC("[");
1946 sStr += rName;
1947 sStr.APPEND_CONST_ASC("] ");
1948 OutField(0, ww::eQUOTE, sStr, WRITEFIELD_START | WRITEFIELD_CMD_START);
1951 void SwWW8Writer::EndCommentOutput(const String& rName)
1953 String sStr(CREATE_CONST_ASC(" ["));
1954 sStr += rName;
1955 sStr.APPEND_CONST_ASC("] ");
1956 OutField(0, ww::eQUOTE, sStr, WRITEFIELD_CMD_END | WRITEFIELD_END |
1957 WRITEFIELD_CLOSE);
1960 USHORT SwWW8Writer::GetId( const SwTOXType& rTOXType )
1962 void* p = (void*)&rTOXType;
1963 USHORT nRet = aTOXArr.GetPos( p );
1964 if( USHRT_MAX == nRet )
1965 aTOXArr.Insert( p, nRet = aTOXArr.Count() );
1966 return nRet;
1969 // return values: 1 - no PageNum,
1970 // 2 - TabStop before PageNum,
1971 // 3 - Text before PageNum - rTxt hold the text
1972 // 4 - no Text and no TabStop before PageNum
1973 int lcl_CheckForm( const SwForm& rForm, BYTE nLvl, String& rText )
1975 int nRet = 4;
1976 rText.Erase();
1978 // #i21237#
1979 SwFormTokens aPattern = rForm.GetPattern(nLvl);
1980 SwFormTokens::iterator aIt = aPattern.begin();
1981 bool bPgNumFnd = false;
1982 FormTokenType eTType;
1984 // #i61362#
1985 if (! aPattern.empty())
1987 // #i21237#
1988 while( ++aIt != aPattern.end() && !bPgNumFnd )
1990 eTType = aIt->eTokenType;
1992 switch( eTType )
1994 case TOKEN_PAGE_NUMS:
1995 bPgNumFnd = true;
1996 break;
1998 case TOKEN_TAB_STOP:
1999 nRet = 2;
2000 break;
2001 case TOKEN_TEXT:
2002 nRet = 3;
2003 rText = aIt->sText.Copy( 0, 5 ); // #i21237#
2004 break;
2006 case TOKEN_LINK_START:
2007 case TOKEN_LINK_END:
2008 break;
2010 default:
2011 nRet = 4;
2012 break;
2016 if( !bPgNumFnd )
2017 nRet = 1;
2020 return nRet;
2023 bool lcl_IsHyperlinked(const SwForm& rForm, USHORT nTOXLvl)
2025 bool bRes = false;
2026 for (USHORT nI = 1; nI < nTOXLvl; ++nI)
2028 // #i21237#
2029 SwFormTokens aPattern = rForm.GetPattern(nI);
2031 if ( !aPattern.empty() )
2033 SwFormTokens::iterator aIt = aPattern.begin();
2035 FormTokenType eTType;
2037 // #i21237#
2038 while ( ++aIt != aPattern.end() )
2040 eTType = aIt->eTokenType;
2041 switch (eTType)
2043 case TOKEN_LINK_START:
2044 case TOKEN_LINK_END:
2045 bRes = true;
2046 break;
2047 default:
2053 return bRes;
2056 void SwWW8Writer::StartTOX( const SwSection& rSect )
2058 if (const SwTOXBase* pTOX = rSect.GetTOXBase())
2060 static const sal_Char sEntryEnd[] = "\" ";
2062 ww::eField eCode = ww::eTOC;
2063 String sStr;
2064 switch (pTOX->GetType())
2066 case TOX_INDEX:
2067 eCode = ww::eINDEX;
2068 sStr = FieldString(eCode);
2070 if (pTOX->GetTOXForm().IsCommaSeparated())
2071 sStr.APPEND_CONST_ASC("\\r ");
2073 if (nsSwTOIOptions::TOI_ALPHA_DELIMITTER & pTOX->GetOptions())
2074 sStr.APPEND_CONST_ASC("\\h \"A\" ");
2077 String aFillTxt;
2078 for (BYTE n = 1; n <= 3; ++n)
2080 String aTxt;
2081 int nRet = ::lcl_CheckForm(pTOX->GetTOXForm(), n, aTxt);
2083 if( 3 == nRet )
2084 aFillTxt = aTxt;
2085 else if ((4 == nRet) || (2 == nRet)) //#109414#
2086 aFillTxt = '\t';
2087 else
2088 aFillTxt.Erase();
2090 sStr.APPEND_CONST_ASC("\\e \"");
2091 sStr += aFillTxt;
2092 sStr.AppendAscii(sEntryEnd);
2094 break;
2096 // case TOX_AUTHORITIES: eCode = eTOA; sStr = ???; break;
2098 case TOX_ILLUSTRATIONS:
2099 case TOX_OBJECTS:
2100 case TOX_TABLES:
2101 if (!pTOX->IsFromObjectNames())
2103 sStr = FieldString(eCode);
2105 sStr.APPEND_CONST_ASC("\\c \"");
2106 sStr += pTOX->GetSequenceName();
2107 sStr.AppendAscii(sEntryEnd);
2109 String aTxt;
2110 int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), 1, aTxt );
2111 if (1 == nRet)
2112 sStr.APPEND_CONST_ASC("\\n ");
2113 else if( 3 == nRet || 4 == nRet )
2115 sStr.APPEND_CONST_ASC("\\p \"");
2116 sStr += aTxt;
2117 sStr.AppendAscii(sEntryEnd);
2120 break;
2122 // case TOX_USER:
2123 // case TOX_CONTENT:
2124 default:
2126 sStr = FieldString(eCode);
2128 String sTOption;
2129 USHORT n, nTOXLvl = pTOX->GetLevel();
2130 if( !nTOXLvl )
2131 ++nTOXLvl;
2133 if( nsSwTOXElement::TOX_MARK & pTOX->GetCreateType() )
2135 sStr.APPEND_CONST_ASC( "\\f " );
2137 if( TOX_USER == pTOX->GetType() )
2139 sStr += '\"';
2140 sStr += (sal_Char)('A' + GetId( *pTOX->GetTOXType()));
2141 sStr.AppendAscii( sEntryEnd );
2145 if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() )
2147 // --> OD 2009-02-27 #i99641#
2148 // The following code does not determine the minimum outline
2149 // level for the TOC
2150 // // Search over all the outline styles used and figure out
2151 // // what is the minimum outline level we need to display
2152 // // (ignoring headline styles 1-9)
2153 // //BYTE nLvl = 0, nMinLvl = 0; //#outline level, removed by zhaojianwei
2154 // int nLvl = 0, nMinLvl = 0; //<-end,add by zhaojianwei
2155 // const SwTxtFmtColls& rColls = *pDoc->GetTxtFmtColls();
2156 // const SwTxtFmtColl* pColl;
2157 // for( n = rColls.Count(); n; )
2158 // {
2159 // pColl = rColls[ --n ];
2160 // //nLvl = pColl->GetOutlineLevel(); //#outline level,zhaojianwei
2161 // //USHORT nPoolId = pColl->GetPoolFmtId();
2162 // //if( MAXLEVEL > nLvl && nMinLvl < nLvl && //<-end, ->add by zhaojianwei
2163 // USHORT nPoolId = pColl->GetPoolFmtId();
2164 // if( pColl->IsAssignedToListLevelOfOutlineStyle() &&
2165 // nMinLvl < (nLvl = pColl->GetAssignedOutlineStyleLevel()) && //<-end,zhaojianwei
2166 // ( RES_POOLCOLL_HEADLINE1 > nPoolId ||
2167 // RES_POOLCOLL_HEADLINE9 < nPoolId ))
2168 // {
2169 // // If we are using the default heading styles then use nTOXLvl
2170 // if(!nMinLvl)
2171 // nLvl = nTOXLvl;
2172 // else
2173 // nLvl = nMinLvl < nTOXLvl ? nMinLvl : (BYTE)nTOXLvl;
2174 // nMinLvl = nLvl;
2175 // }
2176 // }
2177 const int nMinLvl = nTOXLvl;
2179 // if( nLvl )
2180 if ( nMinLvl > 0 )
2182 int nTmpLvl = nMinLvl;
2183 if (nTmpLvl > WW8ListManager::nMaxLevel)
2184 nTmpLvl = WW8ListManager::nMaxLevel;
2186 sStr.APPEND_CONST_ASC( "\\o \"1-" );
2187 sStr += String::CreateFromInt32( nTmpLvl );
2188 sStr.AppendAscii(sEntryEnd);
2191 // <--
2193 // --> OD 2009-02-27 #i99641#
2194 // not needed to additional export paragraph style with
2195 // an outline level to the /t option
2196 // if( nMinLvl > 0 )
2197 // // <--
2198 // {
2199 // // collect this templates into the \t otion
2200 // const SwTxtFmtColls& rColls = *pDoc->GetTxtFmtColls();
2201 // const SwTxtFmtColl* pColl;
2202 // int nLvl = 0;
2203 // for( n = rColls.Count(); n;)
2204 // {
2205 // pColl = rColls[--n];
2206 // //nLvl = pColl->GetOutlineLevel(); //#outline level, removed by zhaojianwei
2207 // //if (MAXLEVEL > nLvl && nMinLvl <= nLvl)
2208 // //{ //<-end, ->add by zhaojianwei
2209 // if( pColl->IsAssignedToListLevelOfOutlineStyle() &&
2210 // nMinLvl <= ( nLvl = pColl->GetAssignedOutlineStyleLevel()))
2211 // { //<-end,zhaojianwei
2212 // if( sTOption.Len() )
2213 // sTOption += ';';
2214 // (( sTOption += pColl->GetName() ) += ';' )
2215 // += String::CreateFromInt32( nLvl + 1 );
2216 // }
2217 // }
2218 // }
2221 if( nsSwTOXElement::TOX_TEMPLATE & pTOX->GetCreateType() )
2222 // --> OD 2009-02-27 #i99641#
2223 // Consider additional styles regardless of TOX-outlinelevel
2224 for( n = 0; n < MAXLEVEL; ++n )
2225 // <--
2227 const String& rStyles = pTOX->GetStyleNames( n );
2228 if( rStyles.Len() )
2230 xub_StrLen nPos = 0;
2231 String sLvl( ';' );
2232 sLvl += String::CreateFromInt32( n + 1 );
2233 do {
2234 String sStyle( rStyles.GetToken( 0,
2235 TOX_STYLE_DELIMITER, nPos ));
2236 if( sStyle.Len() )
2238 if( sTOption.Len() )
2239 sTOption += ';';
2240 ( sTOption += sStyle ) += sLvl;
2242 } while( STRING_NOTFOUND != nPos );
2247 String aFillTxt;
2248 BYTE nNoPgStt = MAXLEVEL, nNoPgEnd = MAXLEVEL;
2249 bool bFirstFillTxt = true, bOnlyText = true;
2250 for( n = 0; n < nTOXLvl; ++n )
2252 String aTxt;
2253 int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(),
2254 static_cast< BYTE >(n+1), aTxt );
2255 if( 1 == nRet )
2257 bOnlyText = false;
2258 if( MAXLEVEL == nNoPgStt )
2259 nNoPgStt = static_cast< BYTE >(n+1);
2261 else
2263 if( MAXLEVEL != nNoPgStt &&
2264 MAXLEVEL == nNoPgEnd )
2265 nNoPgEnd = BYTE(n);
2267 bOnlyText = bOnlyText && 3 == nRet;
2268 if( 3 == nRet || 4 == nRet )
2270 if( bFirstFillTxt )
2271 aFillTxt = aTxt;
2272 else if( aFillTxt != aTxt )
2273 aFillTxt.Erase();
2274 bFirstFillTxt = false;
2278 if( MAXLEVEL != nNoPgStt )
2280 if (WW8ListManager::nMaxLevel < nNoPgEnd)
2281 nNoPgEnd = WW8ListManager::nMaxLevel;
2282 sStr.APPEND_CONST_ASC( "\\n " );
2283 sStr += String::CreateFromInt32( nNoPgStt );
2284 sStr += '-';
2285 sStr += String::CreateFromInt32( nNoPgEnd );
2286 sStr += ' ';
2288 if( bOnlyText )
2290 sStr.APPEND_CONST_ASC( "\\p \"" );
2291 sStr += aFillTxt;
2292 sStr.AppendAscii(sEntryEnd);
2296 if( sTOption.Len() )
2298 sStr.APPEND_CONST_ASC( "\\t \"" );
2299 sStr += sTOption;
2300 sStr.AppendAscii(sEntryEnd);
2303 if (lcl_IsHyperlinked(pTOX->GetTOXForm(), nTOXLvl))
2304 sStr.APPEND_CONST_ASC("\\h");
2306 break;
2309 if( sStr.Len() )
2311 bInWriteTOX = true;
2312 OutField(0, eCode, sStr, WRITEFIELD_START | WRITEFIELD_CMD_START |
2313 WRITEFIELD_CMD_END);
2316 bStartTOX = false;
2319 void SwWW8Writer::EndTOX( const SwSection& rSect )
2321 const SwTOXBase* pTOX = rSect.GetTOXBase();
2322 if( pTOX )
2324 ww::eField eCode = TOX_INDEX == pTOX->GetType() ? ww::eINDEX : ww::eTOC;
2325 OutField(0, eCode, aEmptyStr, WRITEFIELD_CLOSE);
2327 bInWriteTOX = false;
2330 bool SwWW8Writer::GetNumberFmt(const SwField& rFld, String& rStr)
2332 // Returns a date or time format string by using the US NfKeywordTable
2333 bool bHasFmt = false;
2334 SvNumberFormatter* pNFmtr = pDoc->GetNumberFormatter();
2335 UINT32 nFmtIdx = rFld.GetFormat();
2336 const SvNumberformat* pNumFmt = pNFmtr->GetEntry( nFmtIdx );
2337 if( pNumFmt )
2339 //USHORT nLng = rFld.GetLanguage();
2340 LocaleDataWrapper aLocDat( pNFmtr->GetServiceManager(),
2341 MsLangId::convertLanguageToLocale( LANGUAGE_ENGLISH_US ) );
2343 if( !pKeyMap )
2345 pKeyMap = new NfKeywordTable;
2346 NfKeywordTable& rKeyMap = *(NfKeywordTable*)pKeyMap;
2347 pNFmtr->FillKeywordTable( rKeyMap, LANGUAGE_ENGLISH_US );
2350 String sFmt(pNumFmt->GetMappedFormatstring(*(NfKeywordTable*)pKeyMap,
2351 aLocDat));
2352 if (sFmt.Len())
2354 sw::ms::SwapQuotesInField(sFmt);
2356 rStr.APPEND_CONST_ASC( "\\@\"" );
2357 rStr += sFmt;
2358 rStr.APPEND_CONST_ASC( "\" " );
2359 bHasFmt = true;
2362 return bHasFmt;
2365 void WW8_GetNumberPara( String& rStr, const SwField& rFld )
2367 switch(rFld.GetFormat())
2369 case SVX_NUM_CHARS_UPPER_LETTER:
2370 case SVX_NUM_CHARS_UPPER_LETTER_N:
2371 rStr.APPEND_CONST_ASC( "\\*ALPHABETIC ");
2372 break;
2373 case SVX_NUM_CHARS_LOWER_LETTER:
2374 case SVX_NUM_CHARS_LOWER_LETTER_N:
2375 rStr.APPEND_CONST_ASC("\\*alphabetic ");
2376 break;
2377 case SVX_NUM_ROMAN_UPPER:
2378 rStr.APPEND_CONST_ASC("\\*ROMAN ");
2379 break;
2380 case SVX_NUM_ROMAN_LOWER:
2381 rStr.APPEND_CONST_ASC("\\*roman ");
2382 break;
2383 default:
2384 ASSERT(rFld.GetFormat() == SVX_NUM_ARABIC,
2385 "Unknown numbering type exported as default\n");
2386 case SVX_NUM_ARABIC:
2387 rStr.APPEND_CONST_ASC("\\*Arabic ");
2388 break;
2389 case SVX_NUM_PAGEDESC:
2390 //Nothing, use word's default
2391 break;
2395 void SwWW8Writer::WritePostItBegin( WW8Bytes* pOut )
2397 BYTE aArr[ 3 ];
2398 BYTE* pArr = aArr;
2400 // sprmCFSpec true
2401 if( bWrtWW8 )
2402 Set_UInt16( pArr, 0x855 ); //sprmCFSpec
2403 else
2404 Set_UInt8( pArr, 117 ); //sprmCFSpec
2405 Set_UInt8( pArr, 1 );
2407 pChpPlc->AppendFkpEntry( Strm().Tell() );
2408 WriteChar( 0x05 ); // Annotation reference
2410 if( pOut )
2411 pOut->Insert( aArr, static_cast< USHORT >(pArr - aArr), pOut->Count() );
2412 else
2413 pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
2416 String FieldString(ww::eField eIndex)
2418 String sRet(CREATE_CONST_ASC(" "));
2419 if (const char *pField = ww::GetEnglishFieldName(eIndex))
2420 sRet.InsertAscii(pField, 1);
2421 return sRet;
2424 void OutWW8_RefField(SwWW8Writer& rWW8Wrt, const SwField &rFld,
2425 const String &rRef)
2427 String sStr(FieldString(ww::eREF));
2428 sStr.APPEND_CONST_ASC("\"");
2429 sStr += rRef;
2430 sStr.APPEND_CONST_ASC( "\" " );
2431 rWW8Wrt.OutField(&rFld, ww::eREF, sStr, WRITEFIELD_START |
2432 WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
2433 String sVar = lcl_GetExpandedField(rFld);
2434 if (sVar.Len())
2436 if (rWW8Wrt.IsUnicode())
2437 SwWW8Writer::WriteString16(rWW8Wrt.Strm(), sVar, false);
2438 else
2440 SwWW8Writer::WriteString8(rWW8Wrt.Strm(), sVar, false,
2441 RTL_TEXTENCODING_MS_1252);
2444 rWW8Wrt.OutField(&rFld, ww::eREF, sStr, WRITEFIELD_CLOSE);
2447 void WriteExpand(SwWW8Writer& rWW8Wrt, const SwField &rFld)
2449 String sExpand(lcl_GetExpandedField(rFld));
2450 if (rWW8Wrt.IsUnicode())
2451 SwWW8Writer::WriteString16(rWW8Wrt.Strm(), sExpand, false);
2452 else
2454 SwWW8Writer::WriteString8(rWW8Wrt.Strm(), sExpand, false,
2455 RTL_TEXTENCODING_MS_1252);
2459 static Writer& OutWW8_SwField( Writer& rWrt, const SfxPoolItem& rHt )
2461 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
2462 const SwFmtFld& rFld = (SwFmtFld&)rHt;
2463 const SwField* pFld = rFld.GetFld();
2464 String sStr; // fuer optionale Parameter
2465 bool bWriteExpand = false;
2466 USHORT nSubType = pFld->GetSubType();
2468 switch (pFld->GetTyp()->Which())
2470 case RES_GETEXPFLD:
2471 if (nSubType == nsSwGetSetExpType::GSE_STRING)
2473 const SwGetExpField *pGet=(const SwGetExpField*)(pFld);
2474 OutWW8_RefField(rWW8Wrt, *pGet, pGet->GetFormula());
2476 else
2477 bWriteExpand = true;
2478 break;
2479 case RES_SETEXPFLD:
2480 if (nsSwGetSetExpType::GSE_SEQ == nSubType)
2482 sStr = FieldString(ww::eSEQ);
2483 sStr.APPEND_CONST_ASC("\"");
2484 sStr += pFld->GetTyp()->GetName();
2485 sStr.APPEND_CONST_ASC( "\" " );
2487 ::WW8_GetNumberPara( sStr, *pFld );
2488 rWW8Wrt.OutField(pFld, ww::eSEQ, sStr);
2490 else if (nSubType & nsSwGetSetExpType::GSE_STRING)
2492 bool bShowAsWell = false;
2493 ww::eField eFieldNo;
2494 const SwSetExpField *pSet=(const SwSetExpField*)(pFld);
2495 const String &rVar = pSet->GetPar2();
2496 if (pSet->GetInputFlag())
2498 sStr = FieldString(ww::eASK);
2499 sStr.APPEND_CONST_ASC("\"");
2500 sStr += pSet->GetPar1();
2501 sStr.APPEND_CONST_ASC( "\" " );
2502 sStr += pSet->GetPromptText();
2503 sStr.APPEND_CONST_ASC( " \\d " );
2504 sStr += rVar;
2505 eFieldNo = ww::eASK;
2507 else
2509 sStr = FieldString(ww::eSET);
2510 sStr += pSet->GetPar1();
2511 sStr.APPEND_CONST_ASC(" \"");
2512 sStr += rVar;
2513 sStr.APPEND_CONST_ASC("\" ");
2514 eFieldNo = ww::eSET;
2515 bShowAsWell = (nSubType & nsSwExtendedSubType::SUB_INVISIBLE) ? false : true;
2518 ULONG nFrom = rWW8Wrt.Fc2Cp(rWrt.Strm().Tell());
2520 rWW8Wrt.OutField(pFld, eFieldNo, sStr, WRITEFIELD_START |
2521 WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
2524 Is there a bookmark at the start position of this field, if so
2525 move it to the 0x14 of the result of the field. This is what word
2526 does. MoveFieldBookmarks moves any bookmarks at this position to
2527 the beginning of the field result, and marks the bookmark as a
2528 fieldbookmark which is to be ended before the field end mark
2529 instead of after it like a normal bookmark.
2531 rWW8Wrt.MoveFieldBookmarks(nFrom,rWW8Wrt.Fc2Cp(rWrt.Strm().Tell()));
2533 if (rVar.Len())
2535 if (rWW8Wrt.IsUnicode())
2536 SwWW8Writer::WriteString16(rWrt.Strm(), rVar, false);
2537 else
2539 SwWW8Writer::WriteString8(rWrt.Strm(), rVar, false,
2540 RTL_TEXTENCODING_MS_1252);
2543 rWW8Wrt.OutField(pFld, eFieldNo, sStr, WRITEFIELD_CLOSE);
2545 if (bShowAsWell)
2546 OutWW8_RefField(rWW8Wrt, *pSet, pSet->GetPar1());
2548 else
2549 bWriteExpand = true;
2550 break;
2551 case RES_PAGENUMBERFLD:
2552 sStr = FieldString(ww::ePAGE);
2553 ::WW8_GetNumberPara(sStr, *pFld);
2554 rWW8Wrt.OutField(pFld, ww::ePAGE, sStr);
2555 break;
2556 case RES_FILENAMEFLD:
2557 sStr = FieldString(ww::eFILENAME);
2558 if (pFld->GetFormat() == FF_PATHNAME)
2559 sStr.APPEND_CONST_ASC("\\p ");
2560 rWW8Wrt.OutField(pFld, ww::eFILENAME, sStr);
2561 break;
2562 case RES_DBNAMEFLD:
2564 sStr = FieldString(ww::eDATABASE);
2565 SwDBData aData = rWrt.pDoc->GetDBData();
2566 sStr += String(aData.sDataSource);
2567 sStr += DB_DELIM;
2568 sStr += String(aData.sCommand);
2569 rWW8Wrt.OutField(pFld, ww::eDATABASE, sStr);
2571 break;
2572 case RES_AUTHORFLD:
2574 ww::eField eFld =
2575 (AF_SHORTCUT & nSubType ? ww::eUSERINITIALS : ww::eUSERNAME);
2576 rWW8Wrt.OutField(pFld, eFld, FieldString(eFld));
2578 break;
2579 case RES_TEMPLNAMEFLD:
2580 rWW8Wrt.OutField(pFld, ww::eTEMPLATE, FieldString(ww::eTEMPLATE));
2581 break;
2582 case RES_DOCINFOFLD: // Last printed, last edited,...
2583 if( DI_SUB_FIXED & nSubType )
2584 bWriteExpand = true;
2585 else
2587 ww::eField eFld(ww::eNONE);
2588 switch (0xff & nSubType)
2590 case DI_TITEL:
2591 eFld = ww::eTITLE;
2592 break;
2593 case DI_THEMA:
2594 eFld = ww::eSUBJECT;
2595 break;
2596 case DI_KEYS:
2597 eFld = ww::eKEYWORDS;
2598 break;
2599 case DI_COMMENT:
2600 eFld = ww::eCOMMENTS;
2601 break;
2602 case DI_DOCNO:
2603 eFld = ww::eREVNUM;
2604 break;
2605 case DI_CREATE:
2606 if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
2607 eFld = ww::eAUTHOR;
2608 else if (rWW8Wrt.GetNumberFmt(*pFld, sStr))
2609 eFld = ww::eCREATEDATE;
2610 break;
2612 case DI_CHANGE:
2613 if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
2614 eFld = ww::eLASTSAVEDBY;
2615 else if (rWW8Wrt.GetNumberFmt(*pFld, sStr))
2616 eFld = ww::eSAVEDATE;
2617 break;
2619 case DI_PRINT:
2620 if (DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK) &&
2621 rWW8Wrt.GetNumberFmt(*pFld, sStr))
2622 eFld = ww::ePRINTDATE;
2623 break;
2624 case DI_EDIT:
2625 if( DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK ) &&
2626 rWW8Wrt.GetNumberFmt( *pFld, sStr ))
2627 eFld = ww::eSAVEDATE;
2628 break;
2629 case DI_CUSTOM:
2630 eFld = ww::eDOCPROPERTY;
2632 static String sQuotes('\"');
2633 const SwDocInfoField * pDocInfoField =
2634 dynamic_cast<const SwDocInfoField *> (pFld);
2636 if (pDocInfoField != NULL)
2638 String sFieldname = pDocInfoField->GetCntnt(TRUE);
2639 xub_StrLen nIndex = sFieldname.Search(':');
2641 if (nIndex != sFieldname.Len())
2642 sFieldname = sFieldname.Copy(nIndex + 1);
2644 sStr.Insert(sQuotes);
2645 sStr.Insert(sFieldname);
2646 sStr.Insert(sQuotes);
2649 break;
2650 default:
2651 break;
2654 if (eFld != ww::eNONE)
2656 sStr.Insert(FieldString(eFld), 0);
2657 rWW8Wrt.OutField(pFld, eFld, sStr);
2659 else
2660 bWriteExpand = true;
2662 break;
2663 case RES_DATETIMEFLD:
2664 if (FIXEDFLD & nSubType || !rWW8Wrt.GetNumberFmt(*pFld, sStr))
2665 bWriteExpand = true;
2666 else
2668 ww::eField eFld = (DATEFLD & nSubType) ? ww::eDATE : ww::eTIME;
2669 sStr.Insert(FieldString(eFld), 0);
2670 rWW8Wrt.OutField(pFld, eFld, sStr);
2672 break;
2673 case RES_DOCSTATFLD:
2675 ww::eField eFld = ww::eNONE;
2677 switch (nSubType)
2679 case DS_PAGE:
2680 eFld = ww::eNUMPAGE;
2681 break;
2682 case DS_WORD:
2683 eFld = ww::eNUMWORDS;
2684 break;
2685 case DS_CHAR:
2686 eFld = ww::eNUMCHARS;
2687 break;
2690 if (eFld != ww::eNONE)
2692 sStr = FieldString(eFld);
2693 ::WW8_GetNumberPara(sStr, *pFld);
2694 rWW8Wrt.OutField(pFld, eFld, sStr);
2696 else
2697 bWriteExpand = true;
2699 break;
2700 case RES_EXTUSERFLD:
2702 ww::eField eFld = ww::eNONE;
2703 switch (0xFF & nSubType)
2705 case EU_FIRSTNAME:
2706 case EU_NAME:
2707 eFld = ww::eUSERNAME;
2708 break;
2709 case EU_SHORTCUT:
2710 eFld = ww::eUSERINITIALS;
2711 break;
2712 case EU_STREET:
2713 case EU_COUNTRY:
2714 case EU_ZIP:
2715 case EU_CITY:
2716 eFld = ww::eUSERADDRESS;
2717 break;
2720 if (eFld != ww::eNONE)
2722 sStr = FieldString(eFld);
2723 rWW8Wrt.OutField(pFld, eFld, sStr);
2725 else
2726 bWriteExpand = true;
2728 break;
2729 case RES_POSTITFLD:
2730 //Sadly only possible for word in main document text
2731 if (rWW8Wrt.nTxtTyp == TXT_MAINTEXT)
2733 const SwPostItField& rPFld = *(SwPostItField*)pFld;
2734 rWW8Wrt.pAtn->Append( rWW8Wrt.Fc2Cp( rWrt.Strm().Tell() ), rPFld );
2735 rWW8Wrt.WritePostItBegin( rWW8Wrt.pO );
2737 break;
2738 case RES_INPUTFLD:
2740 const SwInputField * pInputField =
2741 dynamic_cast<const SwInputField *>(pFld);
2743 if (pInputField->isFormField())
2744 rWW8Wrt.DoFormText(pInputField);
2745 else
2747 sStr = FieldString(ww::eFILLIN);
2749 sStr.ASSIGN_CONST_ASC("\"");
2750 sStr += pFld->GetPar2();
2751 sStr += '\"';
2753 rWW8Wrt.OutField(pFld, ww::eFILLIN, sStr);
2756 break;
2757 case RES_GETREFFLD:
2759 ww::eField eFld = ww::eNONE;
2760 const SwGetRefField& rRFld = *(SwGetRefField*)pFld;
2761 switch (nSubType)
2763 case REF_SETREFATTR:
2764 case REF_BOOKMARK:
2765 switch (pFld->GetFormat())
2767 case REF_PAGE_PGDESC:
2768 case REF_PAGE:
2769 eFld = ww::ePAGEREF;
2770 break;
2771 default:
2772 eFld = ww::eREF;
2773 break;
2775 sStr = FieldString(eFld);
2776 sStr += rWW8Wrt.GetBookmarkName(nSubType,
2777 &rRFld.GetSetRefName(), 0);
2778 break;
2779 case REF_FOOTNOTE:
2780 case REF_ENDNOTE:
2781 switch (pFld->GetFormat())
2783 case REF_PAGE_PGDESC:
2784 case REF_PAGE:
2785 eFld = ww::ePAGEREF;
2786 break;
2787 case REF_UPDOWN:
2788 eFld = ww::eREF;
2789 break;
2790 default:
2791 eFld =
2792 REF_ENDNOTE == nSubType ? ww::eNOTEREF : ww::eFOOTREF;
2793 break;
2795 sStr = FieldString(eFld);
2796 sStr += rWW8Wrt.GetBookmarkName(nSubType, 0,
2797 rRFld.GetSeqNo());
2798 break;
2801 if (eFld != ww::eNONE)
2803 switch (pFld->GetFormat())
2805 case REF_UPDOWN:
2806 sStr.APPEND_CONST_ASC(" \\p");
2807 break;
2808 case REF_CHAPTER:
2809 sStr.APPEND_CONST_ASC(" \\n");
2810 break;
2811 default:
2812 break;
2814 sStr.APPEND_CONST_ASC(" \\h "); // insert hyperlink
2815 rWW8Wrt.OutField(pFld, eFld, sStr);
2817 else
2818 bWriteExpand = true;
2820 break;
2821 case RES_COMBINED_CHARS:
2824 We need a font size to fill in the defaults, if these are overridden
2825 (as they generally are) by character properties then those properties
2826 win.
2828 The fontsize that is used in MS for determing the defaults is always
2829 the CJK fontsize even if the text is not in that language, in OOo the
2830 largest fontsize used in the field is the one we should take, but
2831 whatever we do, word will actually render using the fontsize set for
2832 CJK text. Nevertheless we attempt to guess whether the script is in
2833 asian or western text based up on the first character and use the
2834 font size of that script as our default.
2836 USHORT nScript;
2837 if( pBreakIt->xBreak.is() )
2838 nScript = pBreakIt->xBreak->getScriptType( pFld->GetPar1(), 0);
2839 else
2840 nScript = i18n::ScriptType::ASIAN;
2842 long nHeight = ((SvxFontHeightItem&)(((SwWW8Writer&)rWrt).GetItem(
2843 GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript)))).GetHeight();;
2845 nHeight = (nHeight + 10) / 20; //Font Size in points;
2848 Divide the combined char string into its up and down part. Get the
2849 font size and fill in the defaults as up == half the font size and
2850 down == a fifth the font size
2852 xub_StrLen nAbove = (pFld->GetPar1().Len()+1)/2;
2853 sStr = FieldString(ww::eEQ);
2854 sStr.APPEND_CONST_ASC("\\o (\\s\\up ");
2855 sStr += String::CreateFromInt32(nHeight/2);
2857 sStr.Append('(');
2858 sStr += String(pFld->GetPar1(),0,nAbove);
2859 sStr.APPEND_CONST_ASC("), \\s\\do ");
2860 sStr += String::CreateFromInt32(nHeight/5);
2862 sStr.Append('(');
2863 sStr += String(pFld->GetPar1(),nAbove,pFld->GetPar1().Len()-nAbove);
2864 sStr.APPEND_CONST_ASC("))");
2865 rWW8Wrt.OutField(pFld, ww::eEQ, sStr);
2867 break;
2868 case RES_DROPDOWN:
2869 if (rWW8Wrt.bWrtWW8)
2871 const SwDropDownField& rFld2 = *(SwDropDownField*)pFld;
2872 uno::Sequence<rtl::OUString> aItems =
2873 rFld2.GetItemSequence();
2874 rWW8Wrt.DoComboBox(rFld2.GetName(),
2875 rFld2.GetHelp(),
2876 rFld2.GetToolTip(),
2877 rFld2.GetSelectedItem(), aItems);
2879 else
2880 bWriteExpand = true;
2881 break;
2882 case RES_CHAPTERFLD:
2883 bWriteExpand = true;
2884 if (rWW8Wrt.bOutKF && rFld.GetTxtFld())
2886 const SwTxtNode *pTxtNd = rWW8Wrt.GetHdFtPageRoot();
2887 if (!pTxtNd)
2889 if (const SwNode *pNd = rWW8Wrt.pCurPam->GetNode())
2890 pTxtNd = pNd->GetTxtNode();
2893 if (pTxtNd)
2895 SwChapterField aCopy(*(const SwChapterField*)pFld);
2896 aCopy.ChangeExpansion(*pTxtNd, false);
2897 WriteExpand(rWW8Wrt, aCopy);
2898 bWriteExpand = false;
2901 break;
2902 case RES_HIDDENTXTFLD:
2904 String sExpand(pFld->GetPar2());
2905 if (sExpand.Len())
2907 //replace LF 0x0A with VT 0x0B
2908 sExpand.SearchAndReplaceAll(0x0A, 0x0B);
2909 rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell());
2910 if (rWW8Wrt.IsUnicode())
2912 SwWW8Writer::WriteString16(rWW8Wrt.Strm(), sExpand, false);
2913 static BYTE aArr[] =
2915 0x3C, 0x08, 0x1
2917 rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(), sizeof(aArr), aArr);
2919 else
2921 SwWW8Writer::WriteString8(rWW8Wrt.Strm(), sExpand, false,
2922 RTL_TEXTENCODING_MS_1252);
2923 static BYTE aArr[] =
2925 92, 0x1
2927 rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(), sizeof(aArr), aArr);
2931 break;
2932 default:
2933 bWriteExpand = true;
2934 break;
2937 if (bWriteExpand)
2938 WriteExpand(rWW8Wrt, *pFld);
2940 return rWrt;
2943 static Writer& OutWW8_SwFlyCntnt( Writer& rWrt, const SfxPoolItem& rHt )
2945 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
2946 if (rWrtWW8.pOutFmtNode && rWrtWW8.pOutFmtNode->ISA(SwCntntNode))
2948 SwTxtNode* pTxtNd = (SwTxtNode*)rWrtWW8.pOutFmtNode;
2950 Point aLayPos;
2951 aLayPos = pTxtNd->FindLayoutRect(false, &aLayPos).Pos();
2953 SwPosition aPos(*pTxtNd);
2954 sw::Frame aFrm(*((const SwFmtFlyCnt&)rHt).GetFrmFmt(), aPos);
2956 rWrtWW8.OutWW8FlyFrm(aFrm, aLayPos);
2958 return rWrt;
2961 // TOXMarks fehlen noch
2963 // Detaillierte Einstellungen zur Trennung erlaubt WW nur dokumentenweise.
2964 // Man koennte folgende Mimik einbauen: Die Werte des Style "Standard" werden,
2965 // falls vorhanden, in die Document Properties ( DOP ) gesetzt.
2966 // ---
2967 // ACK. Dieser Vorschlag passt exakt zu unserer Implementierung des Import,
2968 // daher setze ich das gleich mal um. (KHZ, 07/15/2000)
2969 static Writer& OutWW8_SvxHyphenZone( Writer& rWrt, const SfxPoolItem& rHt )
2971 // sprmPFNoAutoHyph
2972 const SvxHyphenZoneItem& rAttr = (const SvxHyphenZoneItem&)rHt;
2973 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
2974 if( rWrtWW8.bWrtWW8 )
2975 rWrtWW8.InsUInt16( 0x242A );
2976 else
2977 rWrtWW8.pO->Insert( 44, rWrtWW8.pO->Count() );
2979 rWrtWW8.pO->Insert( rAttr.IsHyphen() ? 0 : 1, rWrtWW8.pO->Count() );
2980 return rWrt;
2983 static Writer& OutWW8_SfxBoolItem( Writer& rWrt, const SfxPoolItem& rHt )
2985 USHORT nId = 0;
2986 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
2987 if( rWrtWW8.bWrtWW8 )
2988 switch ( rHt.Which() )
2990 case RES_PARATR_SCRIPTSPACE: nId = 0x2437; break;
2991 case RES_PARATR_HANGINGPUNCTUATION: nId = 0x2435; break;
2992 case RES_PARATR_FORBIDDEN_RULES: nId = 0x2433; break;
2995 if( nId )
2997 if( rWrtWW8.bWrtWW8 )
2998 rWrtWW8.InsUInt16( nId );
2999 else
3000 rWrtWW8.pO->Insert( (BYTE)nId, rWrtWW8.pO->Count() );
3002 rWrtWW8.pO->Insert( ((SfxBoolItem&)rHt).GetValue() ? 1 : 0,
3003 rWrtWW8.pO->Count() );
3005 return rWrt;
3008 static Writer& OutWW8_SvxParaGridItem(Writer& rWrt, const SfxPoolItem& rHt)
3010 // sprmPFUsePgsuSettings
3012 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
3013 //97+ only
3014 if (!rWrtWW8.bWrtWW8)
3015 return rWrt;
3017 rWrtWW8.InsUInt16(0x2447);
3018 const SvxParaGridItem& rAttr = (const SvxParaGridItem&)rHt;
3019 rWrtWW8.pO->Insert( rAttr.GetValue(), rWrtWW8.pO->Count() );
3020 return rWrt;
3023 static Writer& OutWW8_SvxParaVertAlignItem(Writer& rWrt, const SfxPoolItem& rHt)
3025 // sprmPWAlignFont
3027 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
3028 //97+ only
3029 if( !rWrtWW8.bWrtWW8 )
3030 return rWrt;
3032 rWrtWW8.InsUInt16( 0x4439 );
3033 const SvxParaVertAlignItem & rAttr = (const SvxParaVertAlignItem&)rHt;
3035 INT16 nVal = rAttr.GetValue();
3036 switch (nVal)
3038 case SvxParaVertAlignItem::BASELINE:
3039 nVal = 2;
3040 break;
3041 case SvxParaVertAlignItem::TOP:
3042 nVal = 0;
3043 break;
3044 case SvxParaVertAlignItem::CENTER:
3045 nVal = 1;
3046 break;
3047 case SvxParaVertAlignItem::BOTTOM:
3048 nVal = 3;
3049 break;
3050 case SvxParaVertAlignItem::AUTOMATIC:
3051 nVal = 4;
3052 break;
3053 default:
3054 nVal = 4;
3055 ASSERT(!(&rWrt), "Unknown vert alignment");
3056 break;
3058 rWrtWW8.InsUInt16( nVal );
3059 return rWrt;
3063 // NoHyphen: ich habe keine Entsprechung in der SW-UI und WW-UI gefunden
3065 static Writer& OutWW8_SwHardBlank( Writer& rWrt, const SfxPoolItem& rHt )
3067 ((SwWW8Writer&)rWrt).WriteChar( ((SwFmtHardBlank&)rHt).GetChar() );
3068 return rWrt;
3071 // RefMark, NoLineBreakHere fehlen noch
3073 void SwWW8Writer::WriteFtnBegin( const SwFmtFtn& rFtn, WW8Bytes* pOutArr )
3075 WW8Bytes aAttrArr;
3076 bool bAutoNum = !rFtn.GetNumStr().Len(); // Auto-Nummer
3077 if( bAutoNum )
3079 if( bWrtWW8 )
3081 static const BYTE aSpec[] =
3083 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
3084 0x55, 0x08, 1 // sprmCFSpec
3087 aAttrArr.Insert(aSpec, sizeof(aSpec), aAttrArr.Count());
3089 else
3091 static BYTE const aSpec[] =
3093 117, 1, // sprmCFSpec
3094 68, 4, 0, 0, 0, 0 // sprmCObjLocation
3097 aAttrArr.Insert(aSpec, sizeof(aSpec), aAttrArr.Count());
3101 // sprmCIstd
3102 const SwEndNoteInfo* pInfo;
3103 if( rFtn.IsEndNote() )
3104 pInfo = &pDoc->GetEndNoteInfo();
3105 else
3106 pInfo = &pDoc->GetFtnInfo();
3107 const SwCharFmt* pCFmt = pOutArr
3108 ? pInfo->GetAnchorCharFmt( *pDoc )
3109 : pInfo->GetCharFmt( *pDoc );
3110 if( bWrtWW8 )
3111 SwWW8Writer::InsUInt16( aAttrArr, 0x4a30 );
3112 else
3113 aAttrArr.Insert( 80, aAttrArr.Count() );
3114 SwWW8Writer::InsUInt16( aAttrArr, GetId( *pCFmt ) );
3116 // fSpec-Attribut true
3117 // Fuer Auto-Nummer muss ein Spezial-Zeichen
3118 // in den Text und darum ein fSpec-Attribut
3119 pChpPlc->AppendFkpEntry( Strm().Tell() );
3120 if( bAutoNum )
3121 WriteChar( 0x02 ); // Auto-Nummer-Zeichen
3122 else
3123 // User-Nummerierung
3124 OutSwString( rFtn.GetNumStr(), 0, rFtn.GetNumStr().Len(),
3125 IsUnicode(), RTL_TEXTENCODING_MS_1252 );
3127 if( pOutArr )
3129 // insert at start of array, so the "hard" attribute overrule the
3130 // attributes of the character template
3131 pOutArr->Insert( &aAttrArr, 0 );
3133 else
3135 WW8Bytes aOutArr;
3137 // insert at start of array, so the "hard" attribute overrule the
3138 // attributes of the character template
3139 aOutArr.Insert( &aAttrArr, 0 );
3141 // write for the ftn number in the content, the font of the anchor
3142 const SwTxtFtn* pTxtFtn = rFtn.GetTxtFtn();
3143 if( pTxtFtn )
3145 WW8Bytes* pOld = pO;
3146 pO = &aOutArr;
3147 SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_FONT,
3148 RES_CHRATR_FONT );
3150 pCFmt = pInfo->GetCharFmt( *pDoc );
3151 aSet.Set( pCFmt->GetAttrSet() );
3153 pTxtFtn->GetTxtNode().GetAttr( aSet, *pTxtFtn->GetStart(),
3154 (*pTxtFtn->GetStart()) + 1 );
3155 ::OutWW8_SwFont( *this, aSet.Get( RES_CHRATR_FONT ));
3156 pO = pOld;
3158 pChpPlc->AppendFkpEntry( Strm().Tell(), aOutArr.Count(),
3159 aOutArr.GetData() );
3163 static bool lcl_IsAtTxtEnd(const SwFmtFtn& rFtn)
3165 bool bRet = true;
3166 if( rFtn.GetTxtFtn() )
3168 USHORT nWh = static_cast< USHORT >(rFtn.IsEndNote() ? RES_END_AT_TXTEND
3169 : RES_FTN_AT_TXTEND);
3170 const SwSectionNode* pSectNd = rFtn.GetTxtFtn()->GetTxtNode().
3171 FindSectionNode();
3172 while( pSectNd && FTNEND_ATPGORDOCEND ==
3173 ((const SwFmtFtnAtTxtEnd&)pSectNd->GetSection().GetFmt()->
3174 GetFmtAttr( nWh, true)).GetValue() )
3175 pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
3177 if (!pSectNd)
3178 bRet = false; // the is ftn/end collected at Page- or Doc-End
3180 return bRet;
3184 static Writer& OutWW8_SwFtn( Writer& rWrt, const SfxPoolItem& rHt )
3186 const SwFmtFtn& rFtn = (const SwFmtFtn&)rHt;
3187 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3189 USHORT nTyp;
3190 WW8_WrPlcFtnEdn* pFtnEnd;
3191 if( rFtn.IsEndNote() )
3193 pFtnEnd = rWW8Wrt.pEdn;
3194 nTyp = REF_ENDNOTE;
3195 if( rWW8Wrt.bEndAtTxtEnd )
3196 rWW8Wrt.bEndAtTxtEnd = lcl_IsAtTxtEnd( rFtn );
3198 else
3200 pFtnEnd = rWW8Wrt.pFtn;
3201 nTyp = REF_FOOTNOTE;
3202 if( rWW8Wrt.bFtnAtTxtEnd )
3203 rWW8Wrt.bFtnAtTxtEnd = lcl_IsAtTxtEnd( rFtn );
3206 // if any reference to this footnote/endnote then insert an internal
3207 // Bookmark.
3208 String sBkmkNm;
3209 if( rWW8Wrt.HasRefToObject( nTyp, 0, rFtn.GetTxtFtn()->GetSeqRefNo() ))
3211 sBkmkNm = rWW8Wrt.GetBookmarkName( nTyp, 0,
3212 rFtn.GetTxtFtn()->GetSeqRefNo() );
3213 rWW8Wrt.AppendBookmark( sBkmkNm );
3217 pFtnEnd->Append( rWW8Wrt.Fc2Cp( rWrt.Strm().Tell() ), rFtn );
3218 rWW8Wrt.WriteFtnBegin( rFtn, rWW8Wrt.pO );
3220 if( sBkmkNm.Len() )
3221 rWW8Wrt.AppendBookmark( sBkmkNm );
3223 return rWrt;
3226 static Writer& OutWW8_SwTxtCharFmt( Writer& rWrt, const SfxPoolItem& rHt )
3228 const SwFmtCharFmt& rAttr = (const SwFmtCharFmt&)rHt;
3229 if( rAttr.GetCharFmt() )
3231 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
3232 if( rWrtWW8.bWrtWW8 )
3233 rWrtWW8.InsUInt16( 0x4A30 );
3234 else
3235 rWrtWW8.pO->Insert( 80, rWrtWW8.pO->Count() );
3237 rWrtWW8.InsUInt16( rWrtWW8.GetId( *rAttr.GetCharFmt() ) );
3239 return rWrt;
3243 See ww8par6.cxx Read_DoubleLine for some more info
3245 static Writer& OutWW8_SvxTwoLinesItem( Writer& rWrt, const SfxPoolItem& rHt )
3247 // #i28331# - check that bOn is set
3248 if((static_cast<const SvxTwoLinesItem&>(rHt)).GetValue())
3250 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
3251 //97+ only
3252 if( !rWrtWW8.bWrtWW8 )
3253 return rWrt;
3255 const SvxTwoLinesItem& rAttr = (const SvxTwoLinesItem&)rHt;
3256 rWrtWW8.InsUInt16( 0xCA78 );
3257 rWrtWW8.pO->Insert( (BYTE)0x06, rWrtWW8.pO->Count() ); //len 6
3258 rWrtWW8.pO->Insert( (BYTE)0x02, rWrtWW8.pO->Count() );
3260 sal_Unicode cStart = rAttr.GetStartBracket();
3261 sal_Unicode cEnd = rAttr.GetStartBracket();
3264 As per usual we have problems. We can have seperate left and right brackets
3265 in OOo, it doesn't appear that you can in word. Also in word there appear
3266 to only be a limited number of possibilities, we can use pretty much
3267 anything.
3269 So if we have none, we export none, if either bracket is set to a known
3270 word type we export both as that type (with the bracket winning out in
3271 the case of a conflict simply being the order of test here.
3273 Upshot being a documented created in word will be reexported with no
3274 ill effects.
3277 USHORT nType;
3278 if (!cStart && !cEnd)
3279 nType = 0;
3280 else if ((cStart == '{') || (cEnd == '}'))
3281 nType = 4;
3282 else if ((cStart == '<') || (cEnd == '>'))
3283 nType = 3;
3284 else if ((cStart == '[') || (cEnd == ']'))
3285 nType = 2;
3286 else
3287 nType = 1;
3288 rWrtWW8.InsUInt16( nType );
3289 static const BYTE aZeroArr[ 3 ] = { 0, 0, 0 };
3290 rWrtWW8.pO->Insert( aZeroArr, 3, rWrtWW8.pO->Count() );
3292 return rWrt;
3295 static Writer& OutWW8_SwNumRuleItem( Writer& rWrt, const SfxPoolItem& rHt )
3297 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3298 const SwNumRuleItem& rNumRule = (const SwNumRuleItem&)rHt;
3300 const SwTxtNode* pTxtNd = 0;
3301 USHORT nNumId;
3302 BYTE nLvl = 0;
3303 if( rNumRule.GetValue().Len() )
3305 const SwNumRule* pRule = rWrt.pDoc->FindNumRulePtr(
3306 rNumRule.GetValue() );
3307 if( pRule && USHRT_MAX != ( nNumId = rWW8Wrt.GetId( *pRule )) )
3309 ++nNumId;
3310 if( rWW8Wrt.pOutFmtNode )
3312 if( rWW8Wrt.pOutFmtNode->ISA( SwCntntNode ))
3314 pTxtNd = (SwTxtNode*)rWW8Wrt.pOutFmtNode;
3316 if( pTxtNd->IsCountedInList())
3318 nLvl = static_cast< BYTE >(pTxtNd->GetActualListLevel());
3320 if (pTxtNd->IsListRestart())
3322 USHORT nStartWith = static_cast< USHORT >(pTxtNd->GetActualListStartValue());
3323 nNumId = rWW8Wrt.DupNumRuleWithLvlStart(pRule,nLvl,nStartWith);
3324 if (USHRT_MAX != nNumId)
3325 ++nNumId;
3328 else
3330 // #i44815# adjust numbering for numbered paragraphs
3331 // without number (NO_NUMLEVEL). These paragaphs
3332 // will receive a list id 0, which WW interprets as
3333 // 'no number'.
3334 nNumId = 0;
3337 else if( rWW8Wrt.pOutFmtNode->ISA( SwTxtFmtColl ))
3339 const SwTxtFmtColl* pC = (SwTxtFmtColl*)rWW8Wrt.pOutFmtNode;
3340 //if( pC && MAXLEVEL > pC->GetOutlineLevel() ) //#outline level,removed by zhaojianwei
3341 // nLvl = pC->GetOutlineLevel(); //<-end, ->add by zhaojianwei
3342 if( pC && pC->IsAssignedToListLevelOfOutlineStyle() )
3343 nLvl = static_cast<BYTE>(pC->GetAssignedOutlineStyleLevel()); //<-end,zhaojianwei
3347 else
3348 nNumId = USHRT_MAX;
3350 else
3351 nNumId = 0;
3353 if (USHRT_MAX != nNumId)
3355 if (nLvl >= WW8ListManager::nMaxLevel)
3356 nLvl = WW8ListManager::nMaxLevel-1;
3357 if( rWW8Wrt.bWrtWW8 )
3359 // write sprmPIlvl and sprmPIlfo
3360 SwWW8Writer::InsUInt16( *rWW8Wrt.pO, 0x260a );
3361 rWW8Wrt.pO->Insert( nLvl, rWW8Wrt.pO->Count() );
3362 SwWW8Writer::InsUInt16( *rWW8Wrt.pO, 0x460b );
3363 SwWW8Writer::InsUInt16( *rWW8Wrt.pO, nNumId );
3365 else if( pTxtNd && rWW8Wrt.Out_SwNum( pTxtNd ) ) // NumRules
3366 rWW8Wrt.pSepx->SetNum( pTxtNd );
3368 return rWrt;
3371 /* File FRMATR.HXX */
3373 static Writer& OutWW8_SwFrmSize( Writer& rWrt, const SfxPoolItem& rHt )
3375 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3376 const SwFmtFrmSize& rSz = (const SwFmtFrmSize&)rHt;
3378 if( rWW8Wrt.bOutFlyFrmAttrs ) // Flys
3380 if( rWW8Wrt.bOutGrf )
3381 return rWrt; // Fly um Grafik -> Auto-Groesse
3383 //???? was ist bei Prozentangaben ???
3384 if( rSz.GetWidth() && rSz.GetWidthSizeType() == ATT_FIX_SIZE)
3386 //"sprmPDxaWidth"
3387 if( rWW8Wrt.bWrtWW8 )
3388 rWW8Wrt.InsUInt16( 0x841A );
3389 else
3390 rWW8Wrt.pO->Insert( 28, rWW8Wrt.pO->Count() );
3391 rWW8Wrt.InsUInt16( (USHORT)rSz.GetWidth() );
3394 if( rSz.GetHeight() )
3396 // sprmPWHeightAbs
3397 if( rWW8Wrt.bWrtWW8 )
3398 rWW8Wrt.InsUInt16( 0x442B );
3399 else
3400 rWW8Wrt.pO->Insert( 45, rWW8Wrt.pO->Count() );
3402 USHORT nH = 0;
3403 switch( rSz.GetHeightSizeType() )
3405 case ATT_VAR_SIZE: break;
3406 case ATT_FIX_SIZE: nH = (USHORT)rSz.GetHeight() & 0x7fff; break;
3407 default: nH = (USHORT)rSz.GetHeight() | 0x8000; break;
3409 rWW8Wrt.InsUInt16( nH );
3412 else if( rWW8Wrt.bOutPageDescs ) // PageDesc : Breite + Hoehe
3414 if( rWW8Wrt.pAktPageDesc->GetLandscape() )
3416 /*sprmSBOrientation*/
3417 if( rWW8Wrt.bWrtWW8 )
3418 rWW8Wrt.InsUInt16( 0x301d );
3419 else
3420 rWW8Wrt.pO->Insert( 162, rWW8Wrt.pO->Count() );
3421 rWW8Wrt.pO->Insert( 2, rWW8Wrt.pO->Count() );
3424 /*sprmSXaPage*/
3425 if( rWW8Wrt.bWrtWW8 )
3426 rWW8Wrt.InsUInt16( 0xB01F );
3427 else
3428 rWW8Wrt.pO->Insert( 164, rWW8Wrt.pO->Count() );
3429 rWW8Wrt.InsUInt16(
3430 msword_cast<sal_uInt16>(SnapPageDimension(rSz.GetWidth())));
3432 /*sprmSYaPage*/
3433 if( rWW8Wrt.bWrtWW8 )
3434 rWW8Wrt.InsUInt16( 0xB020 );
3435 else
3436 rWW8Wrt.pO->Insert( 165, rWW8Wrt.pO->Count() );
3437 rWW8Wrt.InsUInt16(
3438 msword_cast<sal_uInt16>(SnapPageDimension(rSz.GetHeight())));
3440 return rWrt;
3443 // FillOrder fehlt noch
3445 // ReplaceCr() wird fuer Pagebreaks und Pagedescs gebraucht. Es wird ein
3446 // bereits geschriebenes CR durch ein Break-Zeichen ersetzt. Replace muss
3447 // direkt nach Schreiben des CR gerufen werden.
3448 // Rueckgabe: FilePos des ersetzten CRs + 1 oder 0 fuer nicht ersetzt
3450 ULONG SwWW8Writer::ReplaceCr( BYTE nChar )
3452 // Bug #49917#
3453 ASSERT( nChar, "gegen 0 ersetzt bringt WW97/95 zum Absturz" );
3455 bool bReplaced = false;
3456 SvStream& rStrm = Strm();
3457 ULONG nRetPos = 0, nPos = rStrm.Tell();
3458 BYTE nBCode=0;
3459 UINT16 nUCode=0;
3460 //If there is at least two characters already output
3461 if (nPos - (IsUnicode() ? 2 : 1) >= ULONG(pFib->fcMin))
3463 rStrm.SeekRel(IsUnicode() ? -2 : -1);
3464 if (IsUnicode())
3465 rStrm >> nUCode;
3466 else
3468 rStrm >> nBCode;
3469 nUCode = nBCode;
3471 //If the last char was a cr
3472 if (nUCode == 0x0d) // CR ?
3474 if ((nChar == 0x0c) &&
3475 (nPos - (IsUnicode() ? 4 : 2) >= ULONG(pFib->fcMin)))
3477 rStrm.SeekRel( IsUnicode() ? -4 : -2 );
3478 if (IsUnicode())
3479 rStrm >> nUCode;
3480 else
3482 rStrm >> nUCode;
3483 nUCode = nBCode;
3486 else
3488 rStrm.SeekRel( IsUnicode() ? -2 : -1 );
3489 nUCode = 0x0;
3491 //And the para is not of len 0, then replace this cr with the mark
3492 if( nChar == 0x0e || nUCode == 0x0d )
3493 bReplaced = false;
3494 else
3496 bReplaced = true;
3497 WriteChar(nChar);
3498 nRetPos = nPos;
3501 else if ((nUCode == 0x0c) && (nChar == 0x0e))
3503 //#108854# a column break after a section has
3504 //no effect in writer
3505 bReplaced = true;
3507 rStrm.Seek( nPos );
3509 else
3510 bReplaced = true;
3512 if (!bReplaced)
3514 // then write as normal char
3515 WriteChar(nChar);
3516 pPiece->SetParaBreak();
3517 pPapPlc->AppendFkpEntry(rStrm.Tell());
3518 pChpPlc->AppendFkpEntry(rStrm.Tell());
3519 nRetPos = rStrm.Tell();
3521 #ifdef PRODUCT
3522 else
3524 ASSERT( nRetPos || nPos == (ULONG)pFib->fcMin,
3525 "WW8_ReplaceCr an falscher FilePos gerufen" );
3527 #endif
3528 return nRetPos;
3531 void SwWW8Writer::WriteRowEnd(sal_uInt32 nDepth)
3533 if (nDepth == 1)
3534 WriteChar( (BYTE)0x07 );
3535 else if (nDepth > 1)
3536 WriteChar( (BYTE)0x0d );
3538 //Technically in a word document this is a different value for a row ends
3539 //that are not row ends directly after a cell with a graphic. But it
3540 //doesn't seem to make a difference
3541 //pMagicTable->Append(Fc2Cp(Strm().Tell()),0x1B6);
3544 static Writer& OutWW8_SwFmtPageDesc(Writer& rWrt, const SfxPoolItem& rHt)
3546 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3547 if (rWW8Wrt.bStyDef && rWW8Wrt.pOutFmtNode && rWW8Wrt.pOutFmtNode->ISA(SwTxtFmtColl))
3549 const SwFmtPageDesc &rPgDesc = (const SwFmtPageDesc&)rHt;
3550 const SwTxtFmtColl* pC = (SwTxtFmtColl*)rWW8Wrt.pOutFmtNode;
3551 if ((SFX_ITEM_SET != pC->GetItemState(RES_BREAK, false)) && rPgDesc.GetRegisteredIn())
3552 OutWW8_SwFmtBreak(rWrt, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK));
3554 return rWrt;
3557 // Breaks schreiben nichts in das Ausgabe-Feld rWrt.pO,
3558 // sondern nur in den Text-Stream ( Bedingung dafuer, dass sie von Out_Break...
3559 // gerufen werden duerfen )
3560 static Writer& OutWW8_SwFmtBreak( Writer& rWrt, const SfxPoolItem& rHt )
3562 /*UMSTELLEN*/
3563 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3564 const SvxFmtBreakItem &rBreak = (const SvxFmtBreakItem&)rHt;
3566 if( rWW8Wrt.bStyDef )
3568 switch( rBreak.GetBreak() )
3570 //JP 21.06.99: column breaks does never change to pagebreaks
3571 // case SVX_BREAK_COLUMN_BEFORE:
3572 // case SVX_BREAK_COLUMN_BOTH:
3573 case SVX_BREAK_NONE:
3574 case SVX_BREAK_PAGE_BEFORE:
3575 case SVX_BREAK_PAGE_BOTH:
3576 // sprmPPageBreakBefore/sprmPFPageBreakBefore
3577 if (rWW8Wrt.bWrtWW8)
3578 rWW8Wrt.InsUInt16(0x2407);
3579 else
3580 rWW8Wrt.pO->Insert(9, rWW8Wrt.pO->Count());
3581 rWW8Wrt.pO->Insert(rBreak.GetValue() ? 1 : 0,
3582 rWW8Wrt.pO->Count());
3583 break;
3584 default:
3585 break;
3588 else if (!rWW8Wrt.mpParentFrame)
3590 static const BYTE cColBreak = 0xe;
3591 static const BYTE cPageBreak = 0xc;
3593 BYTE nC = 0;
3594 bool bBefore = false;
3595 // --> OD 2007-05-29 #i76300#
3596 // Note: Can only be <true>, if <bBefore> equals <false>.
3597 bool bCheckForFollowPageDesc = false;
3598 // <--
3600 switch( rBreak.GetBreak() )
3602 case SVX_BREAK_NONE: // Ausgeschaltet
3603 if( !rWW8Wrt.bBreakBefore )
3605 // sprmPPageBreakBefore/sprmPFPageBreakBefore
3606 if( rWW8Wrt.bWrtWW8 )
3607 rWW8Wrt.InsUInt16( 0x2407 );
3608 else
3609 rWW8Wrt.pO->Insert( 9, rWW8Wrt.pO->Count() );
3610 rWW8Wrt.pO->Insert( (BYTE)0, rWW8Wrt.pO->Count() );
3612 return rWrt;
3614 case SVX_BREAK_COLUMN_BEFORE: // ColumnBreak
3615 bBefore = true;
3616 // no break;
3617 case SVX_BREAK_COLUMN_AFTER:
3618 case SVX_BREAK_COLUMN_BOTH:
3619 ASSERT (rWW8Wrt.pSepx, "how come this is 0");
3620 if (rWW8Wrt.pSepx &&
3621 rWW8Wrt.pSepx->CurrentNoColumns(*rWW8Wrt.pDoc) > 1)
3623 nC = cColBreak;
3625 break;
3627 case SVX_BREAK_PAGE_BEFORE: // PageBreak
3628 // From now on(fix for #i77900#) we prefer to save a page break as
3629 // paragraph attribute, this has to be done after the export of the
3630 // paragraph ( => !rWW8Wrt.bBreakBefore )
3631 if( !rWW8Wrt.bBreakBefore )
3633 // sprmPPageBreakBefore/sprmPFPageBreakBefore
3634 if( rWW8Wrt.bWrtWW8 )
3635 rWW8Wrt.InsUInt16( 0x2407 );
3636 else
3637 rWW8Wrt.pO->Insert( 9, rWW8Wrt.pO->Count() );
3638 rWW8Wrt.pO->Insert( (BYTE)1, rWW8Wrt.pO->Count() );
3640 break;
3641 case SVX_BREAK_PAGE_AFTER:
3642 case SVX_BREAK_PAGE_BOTH:
3643 nC = cPageBreak;
3644 // --> OD 2007-05-29 #i76300#
3645 // check for follow page description, if current writing attributes
3646 // of a paragraph.
3647 if ( dynamic_cast<const SwTxtNode*>(rWW8Wrt.pOutFmtNode) &&
3648 rWW8Wrt.GetCurItemSet() )
3650 bCheckForFollowPageDesc = true;
3652 // <--
3653 break;
3654 default:
3655 break;
3658 if ( (bBefore == rWW8Wrt.bBreakBefore ) && nC ) // #49917#
3660 // --> OD 2007-05-29 #i76300#
3661 bool bFollowPageDescWritten( false );
3662 if ( bCheckForFollowPageDesc && !bBefore )
3664 bFollowPageDescWritten =
3665 rWW8Wrt.Out_FollowPageDesc( rWW8Wrt.GetCurItemSet(),
3666 dynamic_cast<const SwTxtNode*>(rWW8Wrt.pOutFmtNode) );
3668 if ( !bFollowPageDescWritten )
3670 rWW8Wrt.ReplaceCr( nC );
3672 // <--
3675 return rWrt;
3678 static Writer& OutWW8_SwTextGrid( Writer& rWrt, const SfxPoolItem& rHt )
3680 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
3681 if (rWrtWW8.bOutPageDescs && rWrtWW8.bWrtWW8)
3683 const SwTextGridItem& rItem = (const SwTextGridItem&)rHt;
3684 UINT16 nGridType=0;
3685 switch (rItem.GetGridType())
3687 default:
3688 ASSERT(!(&rWrt), "Unknown grid type");
3689 case GRID_NONE:
3690 nGridType = 0;
3691 break;
3692 case GRID_LINES_ONLY:
3693 nGridType = 2;
3694 break;
3695 case GRID_LINES_CHARS:
3697 if(rItem.IsSnapToChars())
3699 nGridType = 3;
3701 else
3703 nGridType = 1;
3706 break;
3708 rWrtWW8.InsUInt16(0x5032);
3709 rWrtWW8.InsUInt16(nGridType);
3711 UINT16 nHeight = rItem.GetBaseHeight() + rItem.GetRubyHeight();
3712 rWrtWW8.InsUInt16(0x9031);
3713 rWrtWW8.InsUInt16(nHeight);
3714 sal_uInt32 nPageCharSize = ItemGet<SvxFontHeightItem>(*(rWrtWW8.pStyles->GetSwFmt()),
3715 RES_CHRATR_CJK_FONTSIZE).GetHeight();
3717 INT32 nCharWidth = rItem.GetBaseWidth() - nPageCharSize;
3718 INT32 nFraction = 0;
3719 nFraction = nCharWidth%20;
3720 if( nCharWidth < 0 )
3721 nFraction = 20 + nFraction;
3722 nFraction = ((nFraction)*0xFFF)/20;
3723 nFraction = (nFraction & 0x00000FFF);
3725 INT32 nMain = 0;
3726 nMain = nCharWidth/20;
3727 if( nCharWidth < 0 )
3728 nMain -= 1;
3729 nMain = nMain * 0x1000;
3730 nMain = (nMain & 0xFFFFF000);
3732 UINT32 nCharSpace = nFraction + nMain;
3733 rWrtWW8.InsUInt16(0x7030);
3734 rWrtWW8.InsUInt32(nCharSpace);
3736 return rWrt;
3739 static Writer& OutWW8_SvxPaperBin( Writer& rWrt, const SfxPoolItem& rHt )
3741 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
3742 const SvxPaperBinItem& rItem = (const SvxPaperBinItem&)rHt;
3744 if( rWrtWW8.bOutPageDescs )
3746 USHORT nVal;
3747 switch( rItem.GetValue() )
3749 case 0: nVal = 15; break; // Automatically select
3750 case 1: nVal = 1; break; // Upper paper tray
3751 case 2: nVal = 4; break; // Manual paper feed
3752 default: nVal = 0; break;
3755 if( nVal )
3757 // sprmSDmBinFirst 0x5007 word
3758 // sprmSDmBinOther 0x5008 word
3759 BYTE nOff = rWrtWW8.bOutFirstPage ? 0 : 1;
3760 if( rWrtWW8.bWrtWW8 )
3761 rWrtWW8.InsUInt16( 0x5007 + nOff );
3762 else
3763 rWrtWW8.pO->Insert( 140 + nOff, rWrtWW8.pO->Count() );
3764 rWrtWW8.InsUInt16( nVal );
3767 return rWrt;
3770 static Writer& OutWW8_SwFmtLRSpace( Writer& rWrt, const SfxPoolItem& rHt )
3772 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3773 const SvxLRSpaceItem & rLR = (const SvxLRSpaceItem&) rHt;
3776 // Flys fehlen noch ( siehe RTF )
3778 if( rWW8Wrt.bOutFlyFrmAttrs ) // Flys
3780 // sprmPDxaFromText10
3781 if( rWW8Wrt.bWrtWW8 )
3782 rWW8Wrt.InsUInt16( 0x4622 );
3783 else
3784 rWW8Wrt.pO->Insert( 49, rWW8Wrt.pO->Count() );
3785 // Mittelwert nehmen, da WW nur 1 Wert kennt
3786 rWW8Wrt.InsUInt16( (USHORT) ( ( rLR.GetLeft() + rLR.GetRight() ) / 2 ) );
3788 else if( rWW8Wrt.bOutPageDescs ) // PageDescs
3790 USHORT nLDist, nRDist;
3791 const SfxPoolItem* pItem = ((SwWW8Writer&)rWrt).HasItem( RES_BOX );
3792 if( pItem )
3794 nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
3795 nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
3797 else
3798 nLDist = nRDist = 0;
3799 nLDist = nLDist + (USHORT)rLR.GetLeft();
3800 nRDist = nRDist + (USHORT)rLR.GetRight();
3802 // sprmSDxaLeft
3803 if( rWW8Wrt.bWrtWW8 )
3804 rWW8Wrt.InsUInt16( 0xB021 );
3805 else
3806 rWW8Wrt.pO->Insert( 166, rWW8Wrt.pO->Count() );
3807 rWW8Wrt.InsUInt16( nLDist );
3808 // sprmSDxaRight
3809 if( rWW8Wrt.bWrtWW8 )
3810 rWW8Wrt.InsUInt16( 0xB022 );
3811 else
3812 rWW8Wrt.pO->Insert( 167, rWW8Wrt.pO->Count() );
3813 rWW8Wrt.InsUInt16( nRDist );
3815 else
3816 { // normale Absaetze
3817 // sprmPDxaLeft
3818 if( rWW8Wrt.bWrtWW8 )
3820 rWW8Wrt.InsUInt16( 0x845E ); //asian version ?
3821 rWW8Wrt.InsUInt16( (USHORT)rLR.GetTxtLeft() );
3824 else
3826 rWW8Wrt.pO->Insert( 17, rWW8Wrt.pO->Count() );
3827 rWW8Wrt.InsUInt16( (USHORT)rLR.GetTxtLeft() );
3829 // sprmPDxaRight
3830 if( rWW8Wrt.bWrtWW8 )
3832 rWW8Wrt.InsUInt16( 0x845D ); //asian version ?
3833 rWW8Wrt.InsUInt16( (USHORT)rLR.GetRight() );
3835 else
3837 rWW8Wrt.pO->Insert( 16, rWW8Wrt.pO->Count() );
3838 rWW8Wrt.InsUInt16( (USHORT)rLR.GetRight() );
3840 // sprmPDxaLeft1
3841 if( rWW8Wrt.bWrtWW8 )
3843 rWW8Wrt.InsUInt16( 0x8460 ); //asian version ?
3844 rWW8Wrt.InsUInt16( rLR.GetTxtFirstLineOfst() );
3846 else
3848 rWW8Wrt.pO->Insert( 19, rWW8Wrt.pO->Count() );
3849 rWW8Wrt.InsUInt16( rLR.GetTxtFirstLineOfst() );
3852 return rWrt;
3855 static Writer& OutWW8_SwFmtULSpace( Writer& rWrt, const SfxPoolItem& rHt )
3857 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3858 const SvxULSpaceItem & rUL = (const SvxULSpaceItem&) rHt;
3860 // Flys fehlen noch ( siehe RTF )
3862 if( rWW8Wrt.bOutFlyFrmAttrs ) // Flys
3864 // sprmPDyaFromText
3865 if( rWW8Wrt.bWrtWW8 )
3866 rWW8Wrt.InsUInt16( 0x842E );
3867 else
3868 rWW8Wrt.pO->Insert( 48, rWW8Wrt.pO->Count() );
3869 // Mittelwert nehmen, da WW nur 1 Wert kennt
3870 rWW8Wrt.InsUInt16( (USHORT) ( ( rUL.GetUpper() + rUL.GetLower() ) / 2 ) );
3872 else if( rWW8Wrt.bOutPageDescs ) // Page-UL
3874 ASSERT(rWW8Wrt.GetCurItemSet(), "Impossible");
3875 if (!rWW8Wrt.GetCurItemSet())
3876 return rWrt;
3878 HdFtDistanceGlue aDistances(*rWW8Wrt.GetCurItemSet());
3880 if (aDistances.HasHeader())
3882 //sprmSDyaHdrTop
3883 if (rWW8Wrt.bWrtWW8)
3884 rWW8Wrt.InsUInt16(0xB017);
3885 else
3886 rWW8Wrt.pO->Insert(156, rWW8Wrt.pO->Count());
3887 rWW8Wrt.InsUInt16(aDistances.dyaHdrTop);
3890 // sprmSDyaTop
3891 if (rWW8Wrt.bWrtWW8)
3892 rWW8Wrt.InsUInt16(0x9023);
3893 else
3894 rWW8Wrt.pO->Insert(168, rWW8Wrt.pO->Count());
3895 rWW8Wrt.InsUInt16(aDistances.dyaTop);
3897 if (aDistances.HasFooter())
3899 //sprmSDyaHdrBottom
3900 if (rWW8Wrt.bWrtWW8)
3901 rWW8Wrt.InsUInt16(0xB018);
3902 else
3903 rWW8Wrt.pO->Insert(157, rWW8Wrt.pO->Count());
3904 rWW8Wrt.InsUInt16(aDistances.dyaHdrBottom);
3907 //sprmSDyaBottom
3908 if (rWW8Wrt.bWrtWW8)
3909 rWW8Wrt.InsUInt16(0x9024);
3910 else
3911 rWW8Wrt.pO->Insert(169, rWW8Wrt.pO->Count());
3912 rWW8Wrt.InsUInt16(aDistances.dyaBottom);
3914 else
3916 // sprmPDyaBefore
3917 if( rWW8Wrt.bWrtWW8 )
3918 rWW8Wrt.InsUInt16( 0xA413 );
3919 else
3920 rWW8Wrt.pO->Insert( 21, rWW8Wrt.pO->Count() );
3921 rWW8Wrt.InsUInt16( rUL.GetUpper() );
3922 // sprmPDyaAfter
3923 if( rWW8Wrt.bWrtWW8 )
3924 rWW8Wrt.InsUInt16( 0xA414 );
3925 else
3926 rWW8Wrt.pO->Insert( 22, rWW8Wrt.pO->Count() );
3927 rWW8Wrt.InsUInt16( rUL.GetLower() );
3929 return rWrt;
3932 // Print, Opaque, Protect fehlen noch
3934 static Writer& OutWW8_SwFmtSurround( Writer& rWrt, const SfxPoolItem& rHt )
3936 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3937 if( rWW8Wrt.bOutFlyFrmAttrs )
3939 if( rWW8Wrt.bWrtWW8 )
3940 rWW8Wrt.InsUInt16( 0x2423 );
3941 else
3942 rWW8Wrt.pO->Insert( 37, rWW8Wrt.pO->Count() );
3944 rWW8Wrt.pO->Insert( (SURROUND_NONE !=
3945 ((const SwFmtSurround&) rHt).GetSurround() )
3946 ? 2 : 1, rWW8Wrt.pO->Count() );
3948 return rWrt;
3951 Writer& OutWW8_SwFmtVertOrient( Writer& rWrt, const SfxPoolItem& rHt )
3953 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3955 //!!!! Ankertyp und entsprechende Umrechnung fehlt noch
3957 if( rWW8Wrt.bOutFlyFrmAttrs )
3959 const SwFmtVertOrient& rFlyVert = (const SwFmtVertOrient&) rHt;
3961 short nPos;
3962 switch( rFlyVert.GetVertOrient() )
3964 case text::VertOrientation::NONE:
3965 nPos = (short)rFlyVert.GetPos();
3966 break;
3967 case text::VertOrientation::CENTER:
3968 case text::VertOrientation::LINE_CENTER:
3969 nPos = -8;
3970 break;
3971 case text::VertOrientation::BOTTOM:
3972 case text::VertOrientation::LINE_BOTTOM:
3973 nPos = -12;
3974 break;
3975 case text::VertOrientation::TOP:
3976 case text::VertOrientation::LINE_TOP:
3977 default:
3978 nPos = -4;
3979 break;
3982 // sprmPDyaAbs
3983 if( rWW8Wrt.bWrtWW8 )
3984 rWW8Wrt.InsUInt16( 0x8419 );
3985 else
3986 rWW8Wrt.pO->Insert( 27, rWW8Wrt.pO->Count() );
3987 rWW8Wrt.InsUInt16( nPos );
3989 return rWrt;
3993 Writer& OutWW8_SwFmtHoriOrient( Writer& rWrt, const SfxPoolItem& rHt )
3995 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
3996 if (!rWW8Wrt.mpParentFrame)
3998 ASSERT(rWW8Wrt.mpParentFrame, "HoriOrient without mpParentFrame !!");
3999 return rWrt;
4002 //!!!! Ankertyp und entsprechende Umrechnung fehlt noch
4003 if( rWW8Wrt.bOutFlyFrmAttrs )
4005 const SwFmtHoriOrient& rFlyHori = (const SwFmtHoriOrient&) rHt;
4007 short nPos;
4008 switch( rFlyHori.GetHoriOrient() )
4010 case text::HoriOrientation::NONE: {
4011 nPos = (short)rFlyHori.GetPos();
4012 if( !nPos )
4013 nPos = 1; // WW: 0 ist reserviert
4015 break;
4017 case text::HoriOrientation::LEFT: nPos = rFlyHori.IsPosToggle() ? -12 : 0;
4018 break;
4019 case text::HoriOrientation::RIGHT: nPos = rFlyHori.IsPosToggle() ? -16 : -8;
4020 break;
4021 case text::HoriOrientation::CENTER:
4022 case text::HoriOrientation::FULL: // FULL nur fuer Tabellen
4023 default: nPos = -4; break;
4026 // sprmPDxaAbs
4027 if( rWW8Wrt.bWrtWW8 )
4028 rWW8Wrt.InsUInt16( 0x8418 );
4029 else
4030 rWW8Wrt.pO->Insert( 26, rWW8Wrt.pO->Count() );
4031 rWW8Wrt.InsUInt16( nPos );
4033 return rWrt;
4036 static Writer& OutWW8_SwFmtAnchor( Writer& rWrt, const SfxPoolItem& rHt )
4038 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
4039 ASSERT(rWW8Wrt.mpParentFrame, "Anchor without mpParentFrame !!");
4041 if( rWW8Wrt.bOutFlyFrmAttrs )
4043 const SwFmtAnchor& rAnchor = (const SwFmtAnchor&) rHt;
4044 BYTE nP = 0;
4045 switch( rAnchor.GetAnchorId() )
4047 case FLY_PAGE:
4048 // Vert: Page | Horz: Page
4049 nP |= (1 << 4) | (2 << 6);
4050 break;
4051 // Im Fall eine Flys als Zeichen: Absatz-gebunden setzen!!!
4052 case FLY_AT_FLY:
4053 case FLY_AUTO_CNTNT:
4054 case FLY_AT_CNTNT:
4055 case FLY_IN_CNTNT:
4056 // Vert: Page | Horz: Page
4057 nP |= (2 << 4) | (0 << 6);
4058 break;
4059 default:
4060 break;
4063 // sprmPPc
4064 if( rWW8Wrt.bWrtWW8 )
4065 rWW8Wrt.InsUInt16( 0x261B );
4066 else
4067 rWW8Wrt.pO->Insert( 29, rWW8Wrt.pO->Count() );
4068 rWW8Wrt.pO->Insert( nP, rWW8Wrt.pO->Count() );
4070 return rWrt;
4073 static Writer& OutWW8_SwFmtBackground( Writer& rWrt, const SfxPoolItem& rHt )
4075 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
4077 if( !rWW8Wrt.bOutPageDescs ) // WW kann keinen Hintergrund
4078 { // in Section
4079 const SvxBrushItem& rBack = (const SvxBrushItem&)rHt;
4080 WW8_SHD aSHD;
4082 rWW8Wrt.TransBrush(rBack.GetColor(), aSHD);
4083 // sprmPShd
4084 if (rWW8Wrt.bWrtWW8)
4085 rWW8Wrt.InsUInt16(0x442D);
4086 else
4087 rWW8Wrt.pO->Insert(47, rWW8Wrt.pO->Count());
4088 rWW8Wrt.InsUInt16( aSHD.GetValue() );
4090 //Quite a few unknowns, some might be transparency or something
4091 //of that nature...
4092 if (rWW8Wrt.bWrtWW8)
4094 rWW8Wrt.InsUInt16(0xC64D);
4095 rWW8Wrt.pO->Insert(10, rWW8Wrt.pO->Count());
4096 rWW8Wrt.InsUInt32(0xFF000000);
4097 rWW8Wrt.InsUInt32(SuitableBGColor(
4098 rBack.GetColor().GetColor()));
4099 rWW8Wrt.InsUInt16(0x0000);
4102 return rWrt;
4105 WW8_BRC SwWW8Writer::TranslateBorderLine(const SvxBorderLine& rLine,
4106 USHORT nDist, bool bShadow)
4108 // M.M. This function writes out border lines to the word format similar to
4109 // what SwRTFWriter::OutRTFBorder does in the RTF filter Eventually it
4110 // would be nice if all this functionality was in the one place
4111 WW8_BRC aBrc;
4112 UINT16 nWidth = rLine.GetInWidth() + rLine.GetOutWidth();
4113 BYTE brcType = 0, nColCode = 0;
4115 if( nWidth ) // Linie ?
4117 // BRC.brcType
4118 bool bDouble = 0 != rLine.GetInWidth() && 0 != rLine.GetOutWidth();
4119 bool bThick = !bDouble && !bWrtWW8 && nWidth > 75;
4120 if( bDouble )
4121 brcType = 3;
4122 else if( bThick )
4123 brcType = 2;
4124 else
4125 brcType = 1;
4127 // BRC.dxpLineWidth
4128 if( bThick )
4129 nWidth /= 2;
4131 if( bWrtWW8 )
4133 // Angabe in 8tel Punkten, also durch 2.5, da 1 Punkt = 20 Twips
4134 nWidth = (( nWidth * 8 ) + 10 ) / 20;
4135 if( 0xff < nWidth )
4136 nWidth = 0xff;
4138 else
4140 // Angabe in 0.75 pt
4141 nWidth = ( nWidth + 7 ) / 15;
4142 if( nWidth > 5 )
4143 nWidth = 5;
4146 if( 0 == nWidth ) // ganz duenne Linie
4147 nWidth = 1; // nicht weglassen
4149 // BRC.ico
4150 nColCode = TransCol( rLine.GetColor() );
4153 // BRC.dxpSpace
4154 USHORT nLDist = nDist;
4155 nLDist /= 20; // Masseinheit : pt
4156 if( nLDist > 0x1f )
4157 nLDist = 0x1f;
4159 if( bWrtWW8 )
4161 aBrc.aBits1[0] = BYTE(nWidth);
4162 aBrc.aBits1[1] = brcType;
4163 aBrc.aBits2[0] = nColCode;
4164 aBrc.aBits2[1] = BYTE(nLDist);
4166 // fShadow, keine weiteren Einstellungen im WW moeglich
4167 if( bShadow )
4168 aBrc.aBits2[1] |= 0x20;
4170 else
4172 USHORT aBits = nWidth + ( brcType << 3 );
4173 aBits |= (nColCode & 0x1f) << 6;
4174 aBits |= nLDist << 11;
4175 // fShadow, keine weiteren Einstellungen im WW moeglich
4176 if( bShadow )
4177 aBits |= 0x20;
4178 ShortToSVBT16( aBits, aBrc.aBits1);
4181 return aBrc;
4184 // MakeBorderLine() bekommt einen WW8Bytes* uebergeben, um die Funktion
4185 // auch fuer die Tabellen-Umrandungen zu benutzen.
4186 // Wenn nSprmNo == 0, dann wird der Opcode nicht ausgegeben.
4187 // bShadow darf bei Tabellenzellen *nicht* gesetzt sein !
4188 void SwWW8Writer::Out_BorderLine(WW8Bytes& rO, const SvxBorderLine* pLine,
4189 USHORT nDist, USHORT nOffset, bool bShadow)
4191 ASSERT( (nOffset <= 3) || USHRT_MAX == nOffset ||
4192 ((0x702b - 0x6424) <= nOffset && nOffset <= (0x702e - 0x6424)),
4193 "SprmOffset ausserhalb des Bereichs" );
4195 WW8_BRC aBrc;
4197 if (pLine)
4198 aBrc = TranslateBorderLine( *pLine, nDist, bShadow );
4200 if( bWrtWW8 )
4202 // WW97-SprmIds
4203 // 0x6424, sprmPBrcTop pap.brcTop;BRC;long; !!!!
4204 // 0x6425, sprmPBrcLeft
4205 // 0x6426, sprmPBrcBottom
4206 // 0x6427, sprmPBrcRight
4207 if( USHRT_MAX != nOffset ) // mit OpCode-Ausgabe ?
4208 SwWW8Writer::InsUInt16( rO, 0x6424 + nOffset );
4210 rO.Insert( aBrc.aBits1, 2, rO.Count() );
4211 rO.Insert( aBrc.aBits2, 2, rO.Count() );
4213 else
4215 // WW95-SprmIds
4216 // 38, sprmPBrcTop - pap.brcTop BRC short !!!
4217 // 39, sprmPBrcLeft
4218 // 40, sprmPBrcBottom
4219 // 41, sprmPBrcRight
4220 if( USHRT_MAX != nOffset ) // mit OpCode-Ausgabe ?
4221 rO.Insert( (BYTE)( 38 + nOffset ), rO.Count() );
4222 rO.Insert( aBrc.aBits1, 2, rO.Count() );
4226 // OutWW8_SwFmtBox1() ist fuer alle Boxen ausser in Tabellen.
4227 // es wird pO des WW8Writers genommen
4228 void SwWW8Writer::Out_SwFmtBox(const SvxBoxItem& rBox, bool bShadow)
4230 USHORT nOffset = 0;
4231 if( bOutPageDescs )
4233 if( !bWrtWW8 )
4234 return ; // WW95 kennt keine Seitenumrandung
4236 // WW97-SprmIds
4237 // 0x702b, sprmSBrcTop pap.brcTop;BRC;long; !!!!
4238 // 0x702c, sprmSBrcLeft
4239 // 0x702d, sprmSBrcBottom
4240 // 0x702e, sprmSBrcRight
4241 nOffset = (0x702b - 0x6424);
4244 static const USHORT aBorders[] =
4246 BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
4248 const USHORT* pBrd = aBorders;
4249 for( USHORT i = 0; i < 4; ++i, ++pBrd )
4251 const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
4252 Out_BorderLine( *pO, pLn, rBox.GetDistance( *pBrd ), nOffset+i,
4253 bShadow );
4257 // OutWW8_SwFmtBox2() ist fuer TC-Strukturen in Tabellen. Der Sprm-Opcode
4258 // wird nicht geschrieben, da es in der TC-Structur ohne Opcode gepackt ist.
4259 // dxpSpace wird immer 0, da WW das in Tabellen so verlangt
4260 // ( Tabellenumrandungen fransen sonst aus )
4261 // Ein WW8Bytes-Ptr wird als Ausgabe-Parameter uebergeben
4263 void SwWW8Writer::Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem& rBox )
4265 // moeglich und vielleicht besser waere 0xffff
4266 static const USHORT aBorders[] =
4268 BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
4270 const USHORT* pBrd = aBorders;
4271 for( int i = 0; i < 4; ++i, ++pBrd )
4273 const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
4274 Out_BorderLine(rO, pLn, 0, USHRT_MAX, false);
4278 static Writer& OutWW8_SwFmtBox( Writer& rWrt, const SfxPoolItem& rHt )
4280 // Fly um Grafik-> keine Umrandung hier, da
4281 // der GrafikHeader bereits die Umrandung hat
4282 SwWW8Writer& rWW8Wrt = ((SwWW8Writer&)rWrt);
4283 if( !rWW8Wrt.bOutGrf )
4285 bool bShadow = false;
4286 const SfxPoolItem* pItem = ((SwWW8Writer&)rWrt).HasItem( RES_SHADOW );
4287 if( pItem )
4289 const SvxShadowItem* p = (const SvxShadowItem*)pItem;
4290 bShadow = ( p->GetLocation() != SVX_SHADOW_NONE )
4291 && ( p->GetWidth() != 0 );
4294 rWW8Wrt.Out_SwFmtBox( (SvxBoxItem&)rHt, bShadow );
4296 return rWrt;
4299 SwTwips SwWW8Writer::CurrentPageWidth(SwTwips &rLeft, SwTwips &rRight) const
4301 const SwFrmFmt* pFmt = pAktPageDesc ? &pAktPageDesc->GetMaster()
4302 : &const_cast<const SwDoc *>(pDoc)->GetPageDesc(0).GetMaster();
4304 const SvxLRSpaceItem& rLR = pFmt->GetLRSpace();
4305 SwTwips nPageSize = pFmt->GetFrmSize().GetWidth();
4306 rLeft = rLR.GetLeft();
4307 rRight = rLR.GetRight();
4308 return nPageSize;
4311 static Writer& OutWW8_SwFmtCol( Writer& rWrt, const SfxPoolItem& rHt )
4313 const SwFmtCol& rCol = (const SwFmtCol&)rHt;
4314 const SwColumns& rColumns = rCol.GetColumns();
4315 SwWW8Writer& rWW8Wrt = ((SwWW8Writer&)rWrt);
4317 USHORT nCols = rColumns.Count();
4318 if (1 < nCols && !rWW8Wrt.bOutFlyFrmAttrs)
4320 // dann besorge mal die Seitenbreite ohne Raender !!
4322 const SwFrmFmt* pFmt = rWW8Wrt.pAktPageDesc ? &rWW8Wrt.pAktPageDesc->GetMaster() : &const_cast<const SwDoc *>(rWW8Wrt.pDoc)->GetPageDesc(0).GetMaster();
4323 const SvxFrameDirectionItem &frameDirection = pFmt->GetFrmDir();
4324 SwTwips nPageSize;
4325 if (frameDirection.GetValue() == FRMDIR_VERT_TOP_RIGHT || frameDirection.GetValue() == FRMDIR_VERT_TOP_LEFT)
4327 const SvxULSpaceItem &rUL = pFmt->GetULSpace();
4328 nPageSize = pFmt->GetFrmSize().GetHeight();
4329 nPageSize -= rUL.GetUpper() + rUL.GetLower();
4331 const SwFmtHeader *header = dynamic_cast<const SwFmtHeader *>(pFmt->GetAttrSet().GetItem(RES_HEADER));
4332 if (header)
4334 const SwFrmFmt *headerFmt = header->GetHeaderFmt();
4335 if (headerFmt)
4337 nPageSize -= headerFmt->GetFrmSize().GetHeight();
4340 const SwFmtFooter *footer = dynamic_cast<const SwFmtFooter *>(pFmt->GetAttrSet().GetItem(RES_FOOTER));
4341 if (footer)
4343 const SwFrmFmt *footerFmt = footer->GetFooterFmt();
4344 if (footerFmt)
4346 nPageSize -= footerFmt->GetFrmSize().GetHeight();
4350 else
4352 const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
4353 nPageSize = pFmt->GetFrmSize().GetWidth();
4354 nPageSize -= rLR.GetLeft() + rLR.GetRight();
4357 // CColumns
4358 if( rWW8Wrt.bWrtWW8 )
4359 rWW8Wrt.InsUInt16( 0x500b );
4360 else
4361 rWW8Wrt.pO->Insert( 144, rWW8Wrt.pO->Count() );
4362 rWW8Wrt.InsUInt16( nCols - 1 );
4364 // DxaColumns
4365 if( rWW8Wrt.bWrtWW8 )
4366 rWW8Wrt.InsUInt16( 0x900c );
4367 else
4368 rWW8Wrt.pO->Insert( 145, rWW8Wrt.pO->Count() );
4369 rWW8Wrt.InsUInt16(rCol.GetGutterWidth(true));
4371 // LBetween
4372 if( rWW8Wrt.bWrtWW8 )
4373 rWW8Wrt.InsUInt16( 0x3019 );
4374 else
4375 rWW8Wrt.pO->Insert( 158, rWW8Wrt.pO->Count() );
4376 rWW8Wrt.pO->Insert( COLADJ_NONE == rCol.GetLineAdj() ? 0 : 1,
4377 rWW8Wrt.pO->Count() );
4379 // Nachsehen, ob alle Spalten gleich sind
4380 bool bEven = true;
4381 USHORT n;
4382 USHORT nColWidth = rCol.CalcPrtColWidth( 0, (USHORT)nPageSize );
4383 for (n = 1; n < nCols; n++)
4385 short nDiff = nColWidth -
4386 rCol.CalcPrtColWidth( n, (USHORT)nPageSize );
4388 if( nDiff > 10 || nDiff < -10 ) // Toleranz: 10 tw
4390 bEven = false;
4391 break;
4394 if (bEven)
4396 USHORT nSpace = rColumns[0]->GetRight() + rColumns[1]->GetLeft();
4397 for( n = 2; n < nCols; n++ )
4399 short nDiff = nSpace - ( rColumns[n - 1]->GetRight()
4400 + rColumns[n]->GetLeft() );
4401 if (nDiff > 10 || nDiff < -10)
4403 // Toleranz: 10 tw
4404 bEven = false;
4405 break;
4410 // FEvenlySpaced
4411 if( rWW8Wrt.bWrtWW8 )
4412 rWW8Wrt.InsUInt16( 0x3005 );
4413 else
4414 rWW8Wrt.pO->Insert( 138, rWW8Wrt.pO->Count() );
4415 rWW8Wrt.pO->Insert( bEven ? 1 : 0, rWW8Wrt.pO->Count() );
4417 if( !bEven )
4419 for (n = 0; n < nCols; ++n)
4421 //sprmSDxaColWidth
4422 if( rWW8Wrt.bWrtWW8 )
4423 rWW8Wrt.InsUInt16( 0xF203 );
4424 else
4425 rWW8Wrt.pO->Insert( 136, rWW8Wrt.pO->Count() );
4426 rWW8Wrt.pO->Insert( (BYTE)n, rWW8Wrt.pO->Count() );
4427 rWW8Wrt.InsUInt16(rCol.CalcPrtColWidth(n, (USHORT)nPageSize));
4429 if( n+1 != nCols )
4431 //sprmSDxaColSpacing
4432 if( rWW8Wrt.bWrtWW8 )
4433 rWW8Wrt.InsUInt16( 0xF204 );
4434 else
4435 rWW8Wrt.pO->Insert( 137, rWW8Wrt.pO->Count() );
4436 rWW8Wrt.pO->Insert( (BYTE)n, rWW8Wrt.pO->Count() );
4437 rWW8Wrt.InsUInt16( rColumns[ n ]->GetRight() +
4438 rColumns[ n + 1 ]->GetLeft() );
4443 return rWrt;
4446 // "Absaetze zusammenhalten"
4447 static Writer& OutWW8_SvxFmtKeep( Writer& rWrt, const SfxPoolItem& rHt )
4449 // sprmFKeepFollow
4450 const SvxFmtKeepItem& rAttr = (const SvxFmtKeepItem&)rHt;
4451 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4452 if( rWrtWW8.bWrtWW8 )
4453 rWrtWW8.InsUInt16( 0x2406 );
4454 else
4455 rWrtWW8.pO->Insert( 8, rWrtWW8.pO->Count() );
4457 rWrtWW8.pO->Insert( rAttr.GetValue() ? 1 : 0, rWrtWW8.pO->Count() );
4458 return rWrt;
4462 // exclude a paragraph from Line Numbering
4463 static Writer& OutWW8_SwFmtLineNumber( Writer& rWrt, const SfxPoolItem& rHt )
4465 // sprmPFNoLineNumb
4466 const SwFmtLineNumber& rAttr = (const SwFmtLineNumber&)rHt;
4468 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4469 if( rWrtWW8.bWrtWW8 )
4470 rWrtWW8.InsUInt16( 0x240C );
4471 else
4472 rWrtWW8.pO->Insert( 14, rWrtWW8.pO->Count() );
4474 rWrtWW8.pO->Insert( rAttr.IsCount() ? 0 : 1, rWrtWW8.pO->Count() );
4476 return rWrt;
4480 /* File PARATR.HXX */
4482 static Writer& OutWW8_SvxLineSpacing( Writer& rWrt, const SfxPoolItem& rHt )
4484 // sprmPDyaLine
4485 const SvxLineSpacingItem& rAttr = (const SvxLineSpacingItem&)rHt;
4486 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4487 if( rWrtWW8.bWrtWW8 )
4488 rWrtWW8.InsUInt16( 0x6412 );
4489 else
4490 rWrtWW8.pO->Insert( 20, rWrtWW8.pO->Count() );
4492 short nSpace = 240, nMulti = 0;
4494 switch (rAttr.GetLineSpaceRule())
4496 default:
4497 break;
4498 case SVX_LINE_SPACE_AUTO:
4499 case SVX_LINE_SPACE_FIX:
4500 case SVX_LINE_SPACE_MIN:
4502 switch (rAttr.GetInterLineSpaceRule())
4504 case SVX_INTER_LINE_SPACE_FIX: // unser Durchschuss
4506 // gibt es aber nicht in WW - also wie kommt man an
4507 // die MaxLineHeight heran?
4508 nSpace = (short)rAttr.GetInterLineSpace();
4509 sal_uInt16 nScript =
4510 i18n::ScriptType::LATIN;
4511 const SwAttrSet *pSet = 0;
4512 if (rWrtWW8.pOutFmtNode && rWrtWW8.pOutFmtNode->ISA(SwFmt))
4514 const SwFmt *pFmt = (const SwFmt*)(rWrtWW8.pOutFmtNode);
4515 pSet = &pFmt->GetAttrSet();
4517 else if (rWrtWW8.pOutFmtNode &&
4518 rWrtWW8.pOutFmtNode->ISA(SwTxtNode))
4520 const SwTxtNode* pNd =
4521 (const SwTxtNode*)rWrtWW8.pOutFmtNode;
4522 pSet = &pNd->GetSwAttrSet();
4523 if (pBreakIt->xBreak.is())
4525 nScript = pBreakIt->xBreak->
4526 getScriptType(pNd->GetTxt(), 0);
4529 ASSERT(pSet, "No attrset for lineheight :-(");
4530 if (pSet)
4532 nSpace = nSpace + (short)(AttrSetToLineHeight(*rWrtWW8.pDoc,
4533 *pSet, *Application::GetDefaultDevice(), nScript));
4536 break;
4537 case SVX_INTER_LINE_SPACE_PROP:
4538 nSpace = (short)(( 240L * rAttr.GetPropLineSpace() ) / 100L );
4539 nMulti = 1;
4540 break;
4541 default: // z.B. Minimum oder FIX?
4542 if( SVX_LINE_SPACE_FIX == rAttr.GetLineSpaceRule() )
4543 nSpace = -(short)rAttr.GetLineHeight();
4544 else
4545 nSpace = (short)rAttr.GetLineHeight();
4546 break;
4549 break;
4552 rWrtWW8.InsUInt16(nSpace);
4553 rWrtWW8.InsUInt16(nMulti);
4554 return rWrt;
4557 static Writer& OutWW8_SvxAdjust(Writer& rWrt, const SfxPoolItem& rHt)
4559 // sprmPJc
4560 const SvxAdjustItem& rAttr = (const SvxAdjustItem&)rHt;
4561 BYTE nAdj = 255;
4562 BYTE nAdjBiDi = 255;
4563 switch(rAttr.GetAdjust())
4565 case SVX_ADJUST_LEFT:
4566 nAdj = 0;
4567 nAdjBiDi = 2;
4568 break;
4569 case SVX_ADJUST_RIGHT:
4570 nAdj = 2;
4571 nAdjBiDi = 0;
4572 break;
4573 case SVX_ADJUST_BLOCKLINE:
4574 case SVX_ADJUST_BLOCK:
4575 nAdj = nAdjBiDi = 3;
4576 break;
4577 case SVX_ADJUST_CENTER:
4578 nAdj = nAdjBiDi = 1;
4579 break;
4580 default:
4581 return rWrt; // not a supported Attribut
4584 if (255 != nAdj) // supported Attribut?
4586 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4587 if (rWrtWW8.bWrtWW8)
4589 rWrtWW8.InsUInt16(0x2403);
4590 rWrtWW8.pO->Insert(nAdj, rWrtWW8.pO->Count());
4593 Sadly for left to right paragraphs both these values are the same,
4594 for right to left paragraphs the bidi one is the reverse of the
4595 normal one.
4597 rWrtWW8.InsUInt16(0x2461); //bidi version ?
4598 bool bBiDiSwap=false;
4599 if (rWrtWW8.pOutFmtNode)
4601 short nDirection = FRMDIR_HORI_LEFT_TOP;
4602 if (rWrtWW8.pOutFmtNode->ISA(SwTxtNode))
4604 SwPosition aPos(*(const SwCntntNode*)rWrtWW8.pOutFmtNode);
4605 nDirection = rWrtWW8.pDoc->GetTextDirection(aPos);
4607 else if (rWrtWW8.pOutFmtNode->ISA(SwTxtFmtColl))
4609 const SwTxtFmtColl* pC =
4610 (const SwTxtFmtColl*)rWrtWW8.pOutFmtNode;
4611 const SvxFrameDirectionItem &rItem =
4612 ItemGet<SvxFrameDirectionItem>(*pC, RES_FRAMEDIR);
4613 nDirection = rItem.GetValue();
4615 if ((nDirection == FRMDIR_HORI_RIGHT_TOP)
4616 || (nDirection == FRMDIR_ENVIRONMENT && Application::GetSettings().GetLayoutRTL()))
4617 bBiDiSwap=true;
4620 if (bBiDiSwap)
4621 rWrtWW8.pO->Insert(nAdjBiDi, rWrtWW8.pO->Count());
4622 else
4623 rWrtWW8.pO->Insert(nAdj, rWrtWW8.pO->Count());
4625 else
4627 rWrtWW8.pO->Insert(5, rWrtWW8.pO->Count());
4628 rWrtWW8.pO->Insert(nAdj, rWrtWW8.pO->Count());
4631 return rWrt;
4634 static Writer& OutWW8_SvxFrameDirection( Writer& rWrt, const SfxPoolItem& rHt )
4636 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4637 if (!rWrtWW8.bWrtWW8) //8+ only
4638 return rWrt;
4640 const SvxFrameDirectionItem& rItem = (const SvxFrameDirectionItem&)rHt;
4641 UINT16 nTextFlow=0;
4642 bool bBiDi = false;
4643 short nDir = rItem.GetValue();
4645 if (nDir == FRMDIR_ENVIRONMENT)
4647 if (rWrtWW8.bOutPageDescs)
4648 nDir = rWrtWW8.GetCurrentPageDirection();
4649 else if (rWrtWW8.pOutFmtNode)
4651 if (rWrtWW8.bOutFlyFrmAttrs) //frame
4653 nDir = rWrtWW8.TrueFrameDirection(
4654 *(const SwFrmFmt*)rWrtWW8.pOutFmtNode);
4656 else if (rWrtWW8.pOutFmtNode->ISA(SwCntntNode)) //pagagraph
4658 const SwCntntNode* pNd =
4659 (const SwCntntNode*)rWrtWW8.pOutFmtNode;
4660 SwPosition aPos(*pNd);
4661 nDir = rWrt.pDoc->GetTextDirection(aPos);
4663 else if (rWrtWW8.pOutFmtNode->ISA(SwTxtFmtColl))
4664 nDir = FRMDIR_HORI_LEFT_TOP; //what else can we do :-(
4667 if (nDir == FRMDIR_ENVIRONMENT)
4668 nDir = FRMDIR_HORI_LEFT_TOP; //Set something
4671 switch (nDir)
4673 default:
4674 //Can't get an unknown type here
4675 ASSERT(!(&rWrt), "Unknown frame direction");
4676 case FRMDIR_HORI_LEFT_TOP:
4677 nTextFlow = 0;
4678 break;
4679 case FRMDIR_HORI_RIGHT_TOP:
4680 nTextFlow = 0;
4681 bBiDi = true;
4682 break;
4683 case FRMDIR_VERT_TOP_LEFT: //word doesn't have this
4684 case FRMDIR_VERT_TOP_RIGHT:
4685 nTextFlow = 1;
4686 break;
4689 if (rWrtWW8.bOutPageDescs)
4691 rWrtWW8.InsUInt16(0x5033);
4692 rWrtWW8.InsUInt16(nTextFlow);
4693 rWrtWW8.InsUInt16(0x3228);
4694 rWrtWW8.pO->Insert(bBiDi, rWrtWW8.pO->Count() );
4696 else if (!rWrtWW8.bOutFlyFrmAttrs) //paragraph/style
4698 rWrtWW8.InsUInt16(0x2441);
4699 rWrtWW8.pO->Insert(bBiDi, rWrtWW8.pO->Count() );
4701 return rWrt;
4704 // "Absaetze trennen"
4705 static Writer& OutWW8_SvxFmtSplit( Writer& rWrt, const SfxPoolItem& rHt )
4707 // sprmPFKeep
4708 const SvxFmtSplitItem& rAttr = (const SvxFmtSplitItem&)rHt;
4709 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4710 if( rWrtWW8.bWrtWW8 )
4711 rWrtWW8.InsUInt16( 0x2405 );
4712 else
4713 rWrtWW8.pO->Insert( 7, rWrtWW8.pO->Count() );
4714 rWrtWW8.pO->Insert( rAttr.GetValue() ? 0 : 1, rWrtWW8.pO->Count() );
4715 return rWrt;
4718 // Es wird nur das Item "SvxWidowItem" und nicht die Orphans uebersetzt,
4719 // da es fuer beides im WW nur ein Attribut "Absatzkontrolle" gibt und
4720 // im SW wahrscheinlich vom Anwender immer Beide oder keiner gesetzt werden.
4721 static Writer& OutWW8_SvxWidows( Writer& rWrt, const SfxPoolItem& rHt )
4723 // sprmPFWidowControl
4724 const SvxWidowsItem& rAttr = (const SvxWidowsItem&)rHt;
4725 SwWW8Writer& rWrtWW8 = (SwWW8Writer&)rWrt;
4726 if( rWrtWW8.bWrtWW8 )
4727 rWrtWW8.InsUInt16( 0x2431 );
4728 else
4729 rWrtWW8.pO->Insert( 51, rWrtWW8.pO->Count() );
4730 rWrtWW8.pO->Insert( rAttr.GetValue() ? 1 : 0, rWrtWW8.pO->Count() );
4731 return rWrt;
4735 class SwWW8WrTabu
4737 BYTE* pDel; // DelArray
4738 BYTE* pAddPos; // AddPos-Array
4739 BYTE* pAddTyp; // AddTyp-Array
4740 sal_uInt16 nAdd; // so viele Tabs kommen hinzu
4741 sal_uInt16 nDel; // so viele Tabs fallen weg
4742 public:
4743 SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax);
4744 ~SwWW8WrTabu();
4746 void Add(const SvxTabStop &rTS, long nAdjustment);
4747 void Del(const SvxTabStop &rTS, long nAdjustment);
4748 void PutAll(SwWW8Writer& rWW8Wrt);
4751 SwWW8WrTabu::SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax)
4752 : nAdd(0), nDel(0)
4754 pDel = nDelMax ? new BYTE[nDelMax * 2] : 0;
4755 pAddPos = new BYTE[nAddMax * 2];
4756 pAddTyp = new BYTE[nAddMax];
4759 SwWW8WrTabu::~SwWW8WrTabu()
4761 delete[] pAddTyp;
4762 delete[] pAddPos;
4763 delete[] pDel;
4766 // Add( const SvxTabStop & rTS ) fuegt einen Tab in die WW-Struktur ein
4767 void SwWW8WrTabu::Add(const SvxTabStop & rTS, long nAdjustment)
4769 // Tab-Position eintragen
4770 ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment),
4771 pAddPos + (nAdd * 2));
4773 // Tab-Typ eintragen
4774 BYTE nPara = 0;
4775 switch (rTS.GetAdjustment())
4777 case SVX_TAB_ADJUST_RIGHT:
4778 nPara = 2;
4779 break;
4780 case SVX_TAB_ADJUST_CENTER:
4781 nPara = 1;
4782 break;
4783 case SVX_TAB_ADJUST_DECIMAL:
4785 Theres nothing we can do btw the the decimal seperator has been
4786 customized, but if you think different remember that different
4787 locales have different seperators, i.e. german is a , while english
4788 is a .
4790 nPara = 3;
4791 break;
4792 default:
4793 break;
4796 switch( rTS.GetFill() )
4798 case '.': // dotted leader
4799 nPara |= 1 << 3;
4800 break;
4801 case '_': // Single line leader
4802 nPara |= 3 << 3;
4803 break;
4804 case '-': // hyphenated leader
4805 nPara |= 2 << 3;
4806 break;
4807 case '=': // heavy line leader
4808 nPara |= 4 << 3;
4809 break;
4812 ByteToSVBT8(nPara, pAddTyp + nAdd);
4813 ++nAdd;
4816 // Del( const SvxTabStop & rTS ) fuegt einen zu loeschenden Tab
4817 // in die WW-Struktur ein
4818 void SwWW8WrTabu::Del(const SvxTabStop &rTS, long nAdjustment)
4820 // Tab-Position eintragen
4821 ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment),
4822 pDel + (nDel * 2));
4823 ++nDel;
4826 // PutAll( SwWW8Writer& rWW8Wrt ) schreibt das Attribut nach rWrt.pO
4827 void SwWW8WrTabu::PutAll(SwWW8Writer& rWrt)
4829 if (!nAdd && !nDel) //It its a no-op
4830 return;
4831 ASSERT(nAdd <= 255, "more than 255 added tabstops ?");
4832 ASSERT(nDel <= 255, "more than 244 removed tabstops ?");
4833 if (nAdd > 255)
4834 nAdd = 255;
4835 if (nDel > 255)
4836 nDel = 255;
4838 sal_uInt16 nSiz = 2 * nDel + 3 * nAdd + 2;
4839 if (nSiz > 255)
4840 nSiz = 255;
4842 if (rWrt.bWrtWW8)
4843 rWrt.InsUInt16(0xC60D);
4844 else
4845 rWrt.pO->Insert(15, rWrt.pO->Count());
4846 // cch eintragen
4847 rWrt.pO->Insert(msword_cast<sal_uInt8>(nSiz), rWrt.pO->Count());
4848 // DelArr schreiben
4849 rWrt.pO->Insert(msword_cast<sal_uInt8>(nDel), rWrt.pO->Count());
4850 rWrt.OutSprmBytes(pDel, nDel * 2);
4851 // InsArr schreiben
4852 rWrt.pO->Insert(msword_cast<sal_uInt8>(nAdd), rWrt.pO->Count());
4853 rWrt.OutSprmBytes(pAddPos, 2 * nAdd); // AddPosArray
4854 rWrt.OutSprmBytes(pAddTyp, nAdd); // AddTypArray
4858 static void OutWW8_SwTabStopAdd(Writer& rWrt, const SvxTabStopItem& rTStops,
4859 long nLParaMgn)
4861 SwWW8WrTabu aTab( 0, rTStops.Count());
4863 for( USHORT n = 0; n < rTStops.Count(); n++ )
4865 const SvxTabStop& rTS = rTStops[n];
4866 // Def-Tabs ignorieren
4867 if (SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment())
4868 aTab.Add(rTS, nLParaMgn);
4870 aTab.PutAll( (SwWW8Writer&)rWrt );
4873 bool lcl_IsEqual(long nOneLeft, const SvxTabStop &rOne,
4874 long nTwoLeft, const SvxTabStop &rTwo)
4876 return(
4877 nOneLeft == nTwoLeft &&
4878 rOne.GetAdjustment() == rTwo.GetAdjustment() &&
4879 rOne.GetDecimal() == rTwo.GetDecimal() &&
4880 rOne.GetFill() == rTwo.GetFill()
4884 static void OutWW8_SwTabStopDelAdd(Writer& rWrt, const SvxTabStopItem& rTStyle,
4885 long nLStypeMgn, const SvxTabStopItem& rTNew, long nLParaMgn)
4887 SwWW8WrTabu aTab(rTStyle.Count(), rTNew.Count());
4889 USHORT nO = 0; // rTStyle Index
4890 USHORT nN = 0; // rTNew Index
4892 do {
4893 const SvxTabStop* pTO;
4894 long nOP;
4895 if( nO < rTStyle.Count() ) // alt noch nicht am Ende ?
4897 pTO = &rTStyle[ nO ];
4898 nOP = pTO->GetTabPos() + nLStypeMgn;
4899 if( SVX_TAB_ADJUST_DEFAULT == pTO->GetAdjustment() )
4901 nO++; // Default-Tab ignorieren
4902 continue;
4905 else
4907 pTO = 0;
4908 nOP = LONG_MAX;
4911 const SvxTabStop* pTN;
4912 long nNP;
4913 if( nN < rTNew.Count() ) // neu noch nicht am Ende
4915 pTN = &rTNew[ nN ];
4916 nNP = pTN->GetTabPos() + nLParaMgn;
4917 if( SVX_TAB_ADJUST_DEFAULT == pTN->GetAdjustment() )
4919 nN++; // Default-Tab ignorieren
4920 continue;
4923 else
4925 pTN = 0;
4926 nNP = LONG_MAX;
4929 if( nOP == LONG_MAX && nNP == LONG_MAX )
4930 break; // alles fertig
4932 if( nOP < nNP ) // naechster Tab ist alt
4934 aTab.Del(*pTO, nLStypeMgn); // muss geloescht werden
4935 nO++;
4937 else if( nNP < nOP ) // naechster Tab ist neu
4939 aTab.Add(*pTN, nLParaMgn); // muss eigefuegt werden
4940 nN++;
4942 else if (lcl_IsEqual(nOP, *pTO, nNP, *pTN)) // Tabs sind gleich:
4944 nO++; // nichts zu tun
4945 nN++;
4947 else // Tabs selbe Pos, diff Typ
4949 aTab.Del(*pTO, nLStypeMgn); // alten loeschen
4950 aTab.Add(*pTN, nLParaMgn); // neuen einfuegen
4951 nO++;
4952 nN++;
4954 } while( 1 );
4956 aTab.PutAll( (SwWW8Writer&)rWrt );
4959 static Writer& OutWW8_SwTabStop(Writer& rWrt, const SfxPoolItem& rHt)
4961 SwWW8Writer& rWW8Wrt = (SwWW8Writer&)rWrt;
4962 const SvxTabStopItem & rTStops = (const SvxTabStopItem&)rHt;
4963 const SfxPoolItem* pLR = rWW8Wrt.HasItem( RES_LR_SPACE );
4964 long nCurrentLeft = pLR ? ((const SvxLRSpaceItem*)pLR)->GetTxtLeft() : 0;
4967 // --> FLR 2009-03-17 #i100264#
4968 if (rWW8Wrt.bStyDef
4969 && rWW8Wrt.pCurrentStyle!=NULL
4970 && rWW8Wrt.pCurrentStyle->DerivedFrom()!=NULL) {
4971 SvxTabStopItem aTabs(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP);
4972 const SwFmt *pParentStyle=rWW8Wrt.pCurrentStyle->DerivedFrom();
4973 const SvxTabStopItem* pParentTabs=HasItem<SvxTabStopItem>(pParentStyle->GetAttrSet(), RES_PARATR_TABSTOP);
4974 if (pParentTabs) {
4975 aTabs.Insert(pParentTabs);
4978 OutWW8_SwTabStopDelAdd(rWW8Wrt, aTabs, 0, rTStops, 0);
4979 return rWrt;
4981 // <--
4984 // StyleDef -> "einfach" eintragen || keine Style-Attrs -> dito
4985 const SvxTabStopItem* pStyleTabs = 0;
4986 if (!rWW8Wrt.bStyDef && rWW8Wrt.pStyAttr)
4988 pStyleTabs =
4989 HasItem<SvxTabStopItem>(*rWW8Wrt.pStyAttr, RES_PARATR_TABSTOP);
4992 if (!pStyleTabs)
4993 OutWW8_SwTabStopAdd(rWW8Wrt, rTStops, nCurrentLeft);
4994 else
4996 const SvxLRSpaceItem &rStyleLR =
4997 ItemGet<SvxLRSpaceItem>(*rWW8Wrt.pStyAttr, RES_LR_SPACE);
4998 long nStyleLeft = rStyleLR.GetTxtLeft();
5000 OutWW8_SwTabStopDelAdd(rWW8Wrt, *pStyleTabs, nStyleLeft, rTStops,
5001 nCurrentLeft);
5003 return rWrt;
5006 //-----------------------------------------------------------------------
5009 * lege hier die Tabellen fuer die WW-Funktions-Pointer auf
5010 * die Ausgabe-Funktionen an.
5011 * Es sind lokale Strukturen, die nur innerhalb
5012 * bekannt sein muessen.
5015 SwAttrFnTab aWW8AttrFnTab = {
5016 /* RES_CHRATR_CASEMAP */ OutWW8_SwCaseMap,
5017 /* RES_CHRATR_CHARSETCOLOR */ 0,
5018 /* RES_CHRATR_COLOR */ OutWW8_SwColor,
5019 /* RES_CHRATR_CONTOUR */ OutWW8_SwContour,
5020 /* RES_CHRATR_CROSSEDOUT */ OutWW8_SwCrossedOut,
5021 /* RES_CHRATR_ESCAPEMENT */ OutWW8_SwEscapement,
5022 /* RES_CHRATR_FONT */ OutWW8_SwFont,
5023 /* RES_CHRATR_FONTSIZE */ OutWW8_SwSize,
5024 /* RES_CHRATR_KERNING */ OutWW8_SwKerning,
5025 /* RES_CHRATR_LANGUAGE */ OutWW8_SwLanguage,
5026 /* RES_CHRATR_POSTURE */ OutWW8_SwPosture,
5027 /* RES_CHRATR_PROPORTIONALFONTSIZE*/0,
5028 /* RES_CHRATR_SHADOWED */ OutWW8_SwShadow,
5029 /* RES_CHRATR_UNDERLINE */ OutWW8_SwUnderline,
5030 /* RES_CHRATR_WEIGHT */ OutWW8_SwWeight,
5031 /* RES_CHRATR_WORDLINEMODE */ 0, // Wird bei Underline mitbehandelt
5032 /* RES_CHRATR_AUTOKERN */ OutWW8_SvxAutoKern,
5033 /* RES_CHRATR_BLINK */ OutWW8_SwAnimatedText, // neu: blinkender Text
5034 /* RES_CHRATR_NOHYPHEN */ 0, // Neu: nicht trennen
5035 /* RES_CHRATR_NOLINEBREAK */ 0, // Neu: nicht umbrechen
5036 /* RES_CHRATR_BACKGROUND */ OutWW8_SwFmtCharBackground,
5037 /* RES_CHRATR_CJK_FONT */ OutWW8_SwCJKFont,
5038 /* RES_CHRATR_CJK_FONTSIZE */ OutWW8_SwSize,
5039 /* RES_CHRATR_CJK_LANGUAGE */ OutWW8_SwLanguage,
5040 /* RES_CHRATR_CJK_POSTURE */ OutWW8_SwPosture,
5041 /* RES_CHRATR_CJK_WEIGHT */ OutWW8_SwWeight,
5042 /* RES_CHRATR_CTL_FONT */ OutWW8_SwCTLFont,
5043 /* RES_CHRATR_CTL_FONTSIZE */ OutWW8_SwSize,
5044 /* RES_CHRATR_CTL_LANGUAGE */ OutWW8_SwLanguage,
5045 /* RES_CHRATR_CTL_POSTURE */ OutWW8_SwBiDiPosture,
5046 /* RES_CHRATR_CTL_WEIGHT */ OutWW8_SwBiDiWeight,
5047 /* RES_CHRATR_WRITING_DIRECTION */ OutWW8_CharRotate,
5048 /* RES_CHRATR_EMPHASIS_MARK*/ OutWW8_EmphasisMark,
5049 /* RES_TXTATR_TWO_LINES */ OutWW8_SvxTwoLinesItem,
5050 /* RES_CHRATR_DUMMY4 */ OutWW8_ScaleWidth,
5051 /* RES_CHRATR_RELIEF*/ OutWW8_Relief,
5052 /* RES_CHRATR_HIDDEN */ OutWW8_SvxCharHidden,
5053 /* RES_CHRATR_OVERLINE */ 0,
5054 /* RES_CHRATR_DUMMY1 */ 0,
5055 /* RES_CHRATR_DUMMY2 */ 0,
5057 /* RES_TXTATR_DUMMY4 */ 0,
5058 /* RES_TXTATR_INETFMT */ OutSwFmtINetFmt,
5059 /* RES_TXTATR_REFMARK */ 0, // handled by SwAttrIter
5060 /* RES_TXTATR_TOXMARK */ 0, // handled by SwAttrIter
5061 /* RES_TXTATR_CHARFMT */ OutWW8_SwTxtCharFmt,
5062 /* RES_TXTATR_DUMMY5*/ 0,
5063 /* RES_TXTATR_CJK_RUBY */ 0, // handled by SwAttrIter
5064 /* RES_TXTATR_UNKNOWN_CONTAINER */ 0,
5065 /* RES_TXTATR_DUMMY6 */ 0,
5066 /* RES_TXTATR_DUMMY7 */ 0,
5068 /* RES_TXTATR_FIELD */ OutWW8_SwField,
5069 /* RES_TXTATR_FLYCNT */ OutWW8_SwFlyCntnt,
5070 /* RES_TXTATR_FTN */ OutWW8_SwFtn,
5071 /* RES_TXTATR_SOFTHYPH */ 0, // old attr. - coded now by character
5072 /* RES_TXTATR_HARDBLANK */ OutWW8_SwHardBlank,
5073 /* RES_TXTATR_DUMMY1 */ 0, // Dummy:
5074 /* RES_TXTATR_DUMMY2 */ 0, // Dummy:
5076 /* RES_PARATR_LINESPACING */ OutWW8_SvxLineSpacing,
5077 /* RES_PARATR_ADJUST */ OutWW8_SvxAdjust,
5078 /* RES_PARATR_SPLIT */ OutWW8_SvxFmtSplit,
5079 /* RES_PARATR_ORPHANS */ 0, // OutW4W_SwOrphans, // kann WW nicht unabhaengig von Widows
5080 /* RES_PARATR_WIDOWS */ OutWW8_SvxWidows,
5081 /* RES_PARATR_TABSTOP */ OutWW8_SwTabStop,
5082 /* RES_PARATR_HYPHENZONE*/ OutWW8_SvxHyphenZone,
5083 /* RES_PARATR_DROP */ 0,
5084 /* RES_PARATR_REGISTER */ 0, // neu: Registerhaltigkeit
5085 /* RES_PARATR_NUMRULE */ OutWW8_SwNumRuleItem,
5086 /* RES_PARATR_SCRIPTSPACE */ OutWW8_SfxBoolItem,
5087 /* RES_PARATR_HANGINGPUNCTUATION */ OutWW8_SfxBoolItem,
5088 /* RES_PARATR_FORBIDDEN_RULES */ OutWW8_SfxBoolItem,
5089 /* RES_PARATR_VERTALIGN */ OutWW8_SvxParaVertAlignItem,
5090 /* RES_PARATR_SNAPTOGRID*/ OutWW8_SvxParaGridItem,
5091 /* RES_PARATR_CONNECT_TO_BORDER */ 0, // new
5092 /* RES_PARATR_OUTLINELEVEL */ 0, // new - outlinelevel
5094 /* RES_PARATR_LIST_ID */ 0, // new
5095 /* RES_PARATR_LIST_LEVEL */ 0, // new
5096 /* RES_PARATR_LIST_ISRESTART */ 0, // new
5097 /* RES_PARATR_LIST_RESTARTVALUE */ 0, // new
5098 /* RES_PARATR_LIST_ISCOUNTED */ 0, // new
5100 /* RES_FILL_ORDER */ 0, // OutW4W_SwFillOrder,
5101 /* RES_FRM_SIZE */ OutWW8_SwFrmSize,
5102 /* RES_PAPER_BIN */ OutWW8_SvxPaperBin,
5103 /* RES_LR_SPACE */ OutWW8_SwFmtLRSpace,
5104 /* RES_UL_SPACE */ OutWW8_SwFmtULSpace,
5105 /* RES_PAGEDESC */ OutWW8_SwFmtPageDesc,
5106 /* RES_BREAK */ OutWW8_SwFmtBreak,
5107 /* RES_CNTNT */ 0, /* 0, // OutW4W_??? */
5108 /* RES_HEADER */ 0, // wird bei der PageDesc ausgabe beachtet
5109 /* RES_FOOTER */ 0, // wird bei der PageDesc ausgabe beachtet
5110 /* RES_PRINT */ 0, // OutW4W_SwFmtPrint,
5111 /* RES_OPAQUE */ 0, // OutW4W_SwFmtOpaque, // kann WW nicht
5112 /* RES_PROTECT */ 0, // OutW4W_SwFmtProtect,
5113 /* RES_SURROUND */ OutWW8_SwFmtSurround,
5114 /* RES_VERT_ORIENT */ OutWW8_SwFmtVertOrient,
5115 /* RES_HORI_ORIENT */ OutWW8_SwFmtHoriOrient,
5116 /* RES_ANCHOR */ OutWW8_SwFmtAnchor,
5117 /* RES_BACKGROUND */ OutWW8_SwFmtBackground,
5118 /* RES_BOX */ OutWW8_SwFmtBox,
5119 /* RES_SHADOW */ 0, // Wird bei SwFmtBox mitbehandelt
5120 /* RES_FRMMACRO */ 0, /* 0, // OutW4W_??? */
5121 /* RES_COL */ OutWW8_SwFmtCol,
5122 /* RES_KEEP */ OutWW8_SvxFmtKeep,
5123 /* RES_URL */ 0, // URL
5124 /* RES_EDIT_IN_READONLY */ 0,
5125 /* RES_LAYOUT_SPLIT */ 0,
5126 /* RES_CHAIN */ 0,
5127 /* RES_TEXTGRID*/ OutWW8_SwTextGrid,
5128 /* RES_LINENUMBER */ OutWW8_SwFmtLineNumber, // Line Numbering
5129 /* RES_FTN_AT_TXTEND*/ 0, // Dummy:
5130 /* RES_END_AT_TXTEND*/ 0, // Dummy:
5131 /* RES_COLUMNBALANCE*/ 0, // Dummy:
5132 /* RES_FRAMEDIR*/ OutWW8_SvxFrameDirection,
5133 /* RES_FRMATR_DUMMY8 */ 0, // Dummy:
5134 /* RES_FRMATR_DUMMY9 */ 0, // Dummy:
5135 /* RES_FOLLOW_TEXT_FLOW */ 0,
5136 /* RES_WRAP_INFLUENCE_ON_OBJPOS */ 0,
5137 /* RES_FRMATR_DUMMY2 */ 0, // Dummy:
5138 /* RES_AUTO_STYLE */ 0, // Dummy:
5139 /* RES_FRMATR_DUMMY4 */ 0, // Dummy:
5140 /* RES_FRMATR_DUMMY5 */ 0, // Dummy:
5142 /* RES_GRFATR_MIRRORGRF */ 0, // OutW4W_SwMirrorGrf,
5143 /* RES_GRFATR_CROPGRF */ 0, // OutW4W_SwCropGrf
5144 /* RES_GRFATR_ROTATION */ 0,
5145 /* RES_GRFATR_LUMINANCE */ 0,
5146 /* RES_GRFATR_CONTRAST */ 0,
5147 /* RES_GRFATR_CHANNELR */ 0,
5148 /* RES_GRFATR_CHANNELG */ 0,
5149 /* RES_GRFATR_CHANNELB */ 0,
5150 /* RES_GRFATR_GAMMA */ 0,
5151 /* RES_GRFATR_INVERT */ 0,
5152 /* RES_GRFATR_TRANSPARENCY */ 0,
5153 /* RES_GRFATR_DRWAMODE */ 0,
5154 /* RES_GRFATR_DUMMY1 */ 0,
5155 /* RES_GRFATR_DUMMY2 */ 0,
5156 /* RES_GRFATR_DUMMY3 */ 0,
5157 /* RES_GRFATR_DUMMY4 */ 0,
5158 /* RES_GRFATR_DUMMY5 */ 0,
5160 /* RES_BOXATR_FORMAT */ 0,
5161 /* RES_BOXATR_FORMULA */ 0,
5162 /* RES_BOXATR_VALUE */ 0,
5164 /* RES_UNKNOWNATR_CONTAINER */ 0
5167 /* vi:set tabstop=4 shiftwidth=4 expandtab: */