File: | home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx |
Warning: | line 541, column 21 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ | |||
2 | /* | |||
3 | * This file is part of the LibreOffice project. | |||
4 | * | |||
5 | * This Source Code Form is subject to the terms of the Mozilla Public | |||
6 | * License, v. 2.0. If a copy of the MPL was not distributed with this | |||
7 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |||
8 | * | |||
9 | * This file incorporates work covered by the following license notice: | |||
10 | * | |||
11 | * Licensed to the Apache Software Foundation (ASF) under one or more | |||
12 | * contributor license agreements. See the NOTICE file distributed | |||
13 | * with this work for additional information regarding copyright | |||
14 | * ownership. The ASF licenses this file to you under the Apache | |||
15 | * License, Version 2.0 (the "License"); you may not use this file | |||
16 | * except in compliance with the License. You may obtain a copy of | |||
17 | * the License at http://www.apache.org/licenses/LICENSE-2.0 . | |||
18 | */ | |||
19 | ||||
20 | /* | |||
21 | * This file contains methods for the WW8 output | |||
22 | * (nodes, attributes, formats and chars). | |||
23 | */ | |||
24 | ||||
25 | ||||
26 | #include <algorithm> | |||
27 | #include <hintids.hxx> | |||
28 | ||||
29 | #include <o3tl/safeint.hxx> | |||
30 | #include <vcl/svapp.hxx> | |||
31 | #include <vcl/settings.hxx> | |||
32 | #include <sal/log.hxx> | |||
33 | ||||
34 | #include <svl/zformat.hxx> | |||
35 | #include <svl/itemiter.hxx> | |||
36 | #include <svl/whiter.hxx> | |||
37 | #include <svl/grabbagitem.hxx> | |||
38 | #include <editeng/fontitem.hxx> | |||
39 | #include <editeng/tstpitem.hxx> | |||
40 | #include <editeng/adjustitem.hxx> | |||
41 | #include <editeng/spltitem.hxx> | |||
42 | #include <editeng/widwitem.hxx> | |||
43 | #include <editeng/lspcitem.hxx> | |||
44 | #include <editeng/keepitem.hxx> | |||
45 | #include <editeng/shaditem.hxx> | |||
46 | #include <editeng/brushitem.hxx> | |||
47 | #include <editeng/postitem.hxx> | |||
48 | #include <editeng/wghtitem.hxx> | |||
49 | #include <editeng/kernitem.hxx> | |||
50 | #include <editeng/crossedoutitem.hxx> | |||
51 | #include <editeng/cmapitem.hxx> | |||
52 | #include <editeng/wrlmitem.hxx> | |||
53 | #include <editeng/udlnitem.hxx> | |||
54 | #include <editeng/langitem.hxx> | |||
55 | #include <editeng/escapementitem.hxx> | |||
56 | #include <editeng/fhgtitem.hxx> | |||
57 | #include <editeng/colritem.hxx> | |||
58 | #include <editeng/hyphenzoneitem.hxx> | |||
59 | #include <editeng/formatbreakitem.hxx> | |||
60 | #include <editeng/lrspitem.hxx> | |||
61 | #include <editeng/ulspitem.hxx> | |||
62 | #include <editeng/boxitem.hxx> | |||
63 | #include <editeng/contouritem.hxx> | |||
64 | #include <editeng/shdditem.hxx> | |||
65 | #include <editeng/autokernitem.hxx> | |||
66 | #include <editeng/pbinitem.hxx> | |||
67 | #include <editeng/emphasismarkitem.hxx> | |||
68 | #include <editeng/twolinesitem.hxx> | |||
69 | #include <editeng/charscaleitem.hxx> | |||
70 | #include <editeng/charrotateitem.hxx> | |||
71 | #include <editeng/charreliefitem.hxx> | |||
72 | #include <editeng/paravertalignitem.hxx> | |||
73 | #include <editeng/pgrditem.hxx> | |||
74 | #include <editeng/frmdiritem.hxx> | |||
75 | #include <editeng/blinkitem.hxx> | |||
76 | #include <editeng/charhiddenitem.hxx> | |||
77 | #include <editeng/paperinf.hxx> | |||
78 | #include <svx/xfillit0.hxx> | |||
79 | #include <svx/xflgrit.hxx> | |||
80 | #include <fmtfld.hxx> | |||
81 | #include <fchrfmt.hxx> | |||
82 | #include <fmtfsize.hxx> | |||
83 | #include <fmtpdsc.hxx> | |||
84 | #include <fmtornt.hxx> | |||
85 | #include <fmtanchr.hxx> | |||
86 | #include <fmtclds.hxx> | |||
87 | #include <fmtsrnd.hxx> | |||
88 | #include <fmtftn.hxx> | |||
89 | #include <fmtflcnt.hxx> | |||
90 | #include <frmatr.hxx> | |||
91 | #include <swtable.hxx> | |||
92 | #include <fmtinfmt.hxx> | |||
93 | #include <txtfld.hxx> | |||
94 | #include <txtftn.hxx> | |||
95 | #include <poolfmt.hxx> | |||
96 | #include <doc.hxx> | |||
97 | #include <IDocumentSettingAccess.hxx> | |||
98 | #include <IDocumentFieldsAccess.hxx> | |||
99 | #include <IDocumentStylePoolAccess.hxx> | |||
100 | #include <IDocumentListsAccess.hxx> | |||
101 | #include <list.hxx> | |||
102 | #include <docary.hxx> | |||
103 | #include <pam.hxx> | |||
104 | #include <paratr.hxx> | |||
105 | #include <fldbas.hxx> | |||
106 | #include <docufld.hxx> | |||
107 | #include <expfld.hxx> | |||
108 | #include <pagedesc.hxx> | |||
109 | #include <ndtxt.hxx> | |||
110 | #include <swrect.hxx> | |||
111 | #include <redline.hxx> | |||
112 | #include <reffld.hxx> | |||
113 | #include <ftninfo.hxx> | |||
114 | #include <charfmt.hxx> | |||
115 | #include <section.hxx> | |||
116 | #include <fmtline.hxx> | |||
117 | #include <tox.hxx> | |||
118 | #include <fmtftntx.hxx> | |||
119 | #include <breakit.hxx> | |||
120 | #include <com/sun/star/i18n/ScriptType.hpp> | |||
121 | #include <com/sun/star/i18n/XBreakIterator.hpp> | |||
122 | #include <unotools/localedatawrapper.hxx> | |||
123 | #include <svx/unobrushitemhelper.hxx> | |||
124 | #include <tgrditem.hxx> | |||
125 | #include <flddropdown.hxx> | |||
126 | #include <chpfld.hxx> | |||
127 | #include <fmthdft.hxx> | |||
128 | #include <authfld.hxx> | |||
129 | #include <dbfld.hxx> | |||
130 | ||||
131 | #include "sprmids.hxx" | |||
132 | ||||
133 | #include <fmtcntnt.hxx> | |||
134 | #include "writerhelper.hxx" | |||
135 | #include "writerwordglue.hxx" | |||
136 | #include "wrtww8.hxx" | |||
137 | #include "ww8par.hxx" | |||
138 | #include "ww8attributeoutput.hxx" | |||
139 | #include "fields.hxx" | |||
140 | #include <i18nlangtag/languagetag.hxx> | |||
141 | #include <unotools/fltrcfg.hxx> | |||
142 | ||||
143 | ||||
144 | using ::editeng::SvxBorderLine; | |||
145 | using namespace ::com::sun::star; | |||
146 | using namespace nsSwDocInfoSubType; | |||
147 | using namespace sw::util; | |||
148 | using namespace sw::types; | |||
149 | ||||
150 | bool WW8Export::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich ) | |||
151 | { | |||
152 | bool bRet = true; | |||
153 | if ( nScript == i18n::ScriptType::ASIAN ) | |||
154 | { | |||
155 | //for asian in ww8, there is only one fontsize | |||
156 | //and one fontstyle (posture/weight) for ww6 | |||
157 | //there is the additional problem that there | |||
158 | //is only one font setting for all three scripts | |||
159 | switch ( nWhich ) | |||
160 | { | |||
161 | case RES_CHRATR_FONTSIZE: | |||
162 | case RES_CHRATR_POSTURE: | |||
163 | case RES_CHRATR_WEIGHT: | |||
164 | bRet = false; | |||
165 | break; | |||
166 | case RES_CHRATR_LANGUAGE: | |||
167 | case RES_CHRATR_CTL_FONT: | |||
168 | case RES_CHRATR_CTL_FONTSIZE: | |||
169 | case RES_CHRATR_CTL_LANGUAGE: | |||
170 | case RES_CHRATR_CTL_POSTURE: | |||
171 | case RES_CHRATR_CTL_WEIGHT: | |||
172 | default: | |||
173 | break; | |||
174 | } | |||
175 | } | |||
176 | else if ( nScript == i18n::ScriptType::COMPLEX ) | |||
177 | { | |||
178 | //Complex is ok in ww8, but for ww6 there is only | |||
179 | //one font, one fontsize, one fontsize (weight/posture) | |||
180 | //and only one language | |||
181 | } | |||
182 | else | |||
183 | { | |||
184 | //for western in ww8, there is only one fontsize | |||
185 | //and one fontstyle (posture/weight) for ww6 | |||
186 | //there is the additional problem that there | |||
187 | //is only one font setting for all three scripts | |||
188 | switch ( nWhich ) | |||
189 | { | |||
190 | case RES_CHRATR_CJK_FONTSIZE: | |||
191 | case RES_CHRATR_CJK_POSTURE: | |||
192 | case RES_CHRATR_CJK_WEIGHT: | |||
193 | bRet = false; | |||
194 | break; | |||
195 | case RES_CHRATR_CJK_LANGUAGE: | |||
196 | case RES_CHRATR_CTL_FONT: | |||
197 | case RES_CHRATR_CTL_FONTSIZE: | |||
198 | case RES_CHRATR_CTL_LANGUAGE: | |||
199 | case RES_CHRATR_CTL_POSTURE: | |||
200 | case RES_CHRATR_CTL_WEIGHT: | |||
201 | default: | |||
202 | break; | |||
203 | } | |||
204 | } | |||
205 | return bRet; | |||
206 | } | |||
207 | ||||
208 | ||||
209 | void MSWordExportBase::ExportPoolItemsToCHP( ww8::PoolItems &rItems, sal_uInt16 nScript, const SvxFontItem *pFont, bool bWriteCombChars ) | |||
210 | { | |||
211 | for ( const auto& rItem : rItems ) | |||
212 | { | |||
213 | const SfxPoolItem *pItem = rItem.second; | |||
214 | sal_uInt16 nWhich = pItem->Which(); | |||
215 | if ( ( isCHRATR( nWhich ) || isTXTATR( nWhich ) ) && CollapseScriptsforWordOk( nScript, nWhich ) ) | |||
216 | { | |||
217 | //In the id definition, RES_TXTATR_INETFMT must precede RES_TXTATR_CHARFMT, so that link style can overwrite char style. | |||
218 | //and in #i24291# it describes "All we want to do is ensure for now is that if a charfmt exist in the character | |||
219 | //properties that it rises to the top and is exported first." | |||
220 | //In bug 119649, it is in such situation, so we need to ignore the link style when doing ms word filter exports and | |||
221 | //add the second judgement for #i24291# definition. | |||
222 | if (nWhich == RES_TXTATR_CHARFMT) | |||
223 | { | |||
224 | const SfxPoolItem* pINetItem = SearchPoolItems(rItems, RES_TXTATR_INETFMT); | |||
225 | ||||
226 | if (pINetItem) | |||
227 | { | |||
228 | const SwFormatINetFormat& rINet = static_cast<const SwFormatINetFormat&>(*pINetItem); | |||
229 | const SwCharFormat* pINetFormat = GetSwCharFormat(rINet, m_rDoc); | |||
230 | if (!pINetFormat) | |||
231 | continue; | |||
232 | ||||
233 | const SwCharFormat* pFormat = static_cast<const SwFormatCharFormat&>(*pItem).GetCharFormat(); | |||
234 | ww8::PoolItems aCharItems, aINetItems; | |||
235 | GetPoolItems(pFormat->GetAttrSet(), aCharItems, false); | |||
236 | GetPoolItems(pINetFormat->GetAttrSet(), aINetItems, false); | |||
237 | for (const auto& rCharItem : aCharItems) | |||
238 | { | |||
239 | const SfxPoolItem* pCharItem = rCharItem.second; | |||
240 | sal_uInt16 nCharWhich = pCharItem->Which(); | |||
241 | if (!SearchPoolItems(aINetItems, nCharWhich) && !SearchPoolItems(rItems, nCharWhich)) | |||
242 | AttrOutput().OutputItem(*pCharItem); | |||
243 | } | |||
244 | continue; | |||
245 | } | |||
246 | } | |||
247 | ||||
248 | // tdf#38778 Fix output of the font in DOC run for fields | |||
249 | if (pFont && | |||
250 | nWhich == RES_TXTATR_FIELD) | |||
251 | { | |||
252 | AttrOutput().OutputItem( *pFont ); | |||
253 | } | |||
254 | ||||
255 | // tdf#66401 For Combined Characters in docx, MS Word uses half the normal font-size for the field's | |||
256 | // font-size, but only for <w:sz>. Therefore, we check if we are currently writing a field of type | |||
257 | // Combined Characters and if so, we half the font size. | |||
258 | if (bWriteCombChars && | |||
259 | nWhich == RES_CHRATR_FONTSIZE) | |||
260 | { | |||
261 | SvxFontHeightItem fontHeight(item_cast<SvxFontHeightItem>( *pItem )); | |||
262 | fontHeight.SetHeight( fontHeight.GetHeight() / 2 ); | |||
263 | ||||
264 | AttrOutput().OutputItem( fontHeight ); | |||
265 | } | |||
266 | else if (nWhich == RES_CHRATR_COLOR) | |||
267 | { | |||
268 | const SvxColorItem& rColor = static_cast<const SvxColorItem&>(*pItem); | |||
269 | const SfxPoolItem* pBackgroundItem = SearchPoolItems(rItems, RES_CHRATR_BACKGROUND); | |||
270 | if (rColor.GetValue() == COL_AUTO && pBackgroundItem) | |||
271 | { | |||
272 | const SvxBrushItem& rBrushBackground = static_cast<const SvxBrushItem&>(*pBackgroundItem); | |||
273 | SvxColorItem aForeground(rBrushBackground.GetColor().IsDark() ? COL_WHITE : COL_BLACK, RES_CHRATR_COLOR); | |||
274 | AttrOutput().OutputItem(aForeground); | |||
275 | } | |||
276 | else | |||
277 | { | |||
278 | // default | |||
279 | AttrOutput().OutputItem( *pItem ); | |||
280 | } | |||
281 | } | |||
282 | else | |||
283 | { | |||
284 | AttrOutput().OutputItem( *pItem ); | |||
285 | } | |||
286 | } | |||
287 | } | |||
288 | } | |||
289 | ||||
290 | /* | |||
291 | * Output format as follows: | |||
292 | * - output the attributes; without parents! | |||
293 | */ | |||
294 | ||||
295 | void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFormat, bool bChpFormat, sal_uInt16 nScript, | |||
296 | bool bExportParentItemSet ) | |||
297 | { | |||
298 | if( !(bExportParentItemSet || rSet.Count()) ) | |||
299 | return; | |||
300 | ||||
301 | const SfxPoolItem* pItem; | |||
302 | m_pISet = &rSet; // for double attributes | |||
303 | ||||
304 | // If frame dir is set, but not adjust, then force adjust as well | |||
305 | if ( bPapFormat && SfxItemState::SET == rSet.GetItemState( RES_FRAMEDIR, bExportParentItemSet ) ) | |||
306 | { | |||
307 | // No explicit adjust set ? | |||
308 | if ( SfxItemState::SET != rSet.GetItemState( RES_PARATR_ADJUST, bExportParentItemSet ) ) | |||
309 | { | |||
310 | pItem = rSet.GetItem( RES_PARATR_ADJUST, bExportParentItemSet ); | |||
311 | if ( nullptr != pItem ) | |||
312 | { | |||
313 | // then set the adjust used by the parent format | |||
314 | AttrOutput().OutputItem( *pItem ); | |||
315 | } | |||
316 | } | |||
317 | } | |||
318 | ||||
319 | if ( bPapFormat && SfxItemState::SET == rSet.GetItemState( RES_PARATR_NUMRULE, bExportParentItemSet, &pItem ) ) | |||
320 | { | |||
321 | AttrOutput().OutputItem( *pItem ); | |||
322 | ||||
323 | // switch off the numbering? | |||
324 | if ( static_cast<const SwNumRuleItem*>(pItem)->GetValue().isEmpty() && | |||
325 | SfxItemState::SET != rSet.GetItemState( RES_LR_SPACE, false) && | |||
326 | SfxItemState::SET == rSet.GetItemState( RES_LR_SPACE, true, &pItem ) ) | |||
327 | { | |||
328 | // the set the LR-Space of the parentformat! | |||
329 | AttrOutput().OutputItem( *pItem ); | |||
330 | } | |||
331 | } | |||
332 | ||||
333 | ww8::PoolItems aItems; | |||
334 | GetPoolItems( rSet, aItems, bExportParentItemSet ); | |||
335 | if ( bChpFormat ) | |||
336 | ExportPoolItemsToCHP(aItems, nScript, nullptr); | |||
337 | if ( bPapFormat ) | |||
338 | { | |||
339 | AttrOutput().MaybeOutputBrushItem(rSet); | |||
340 | ||||
341 | for ( const auto& rItem : aItems ) | |||
342 | { | |||
343 | pItem = rItem.second; | |||
344 | sal_uInt16 nWhich = pItem->Which(); | |||
345 | // Handle fill attributes just like frame attributes for now. | |||
346 | if ( (nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END && nWhich != RES_PARATR_NUMRULE ) || | |||
347 | (nWhich >= XATTR_FILL_FIRST && nWhich < XATTR_FILL_LAST)) | |||
348 | AttrOutput().OutputItem( *pItem ); | |||
349 | } | |||
350 | ||||
351 | // Has to be called after RES_PARATR_GRABBAG is processed. | |||
352 | const XFillStyleItem* pXFillStyleItem(rSet.GetItem<XFillStyleItem>(XATTR_FILLSTYLE)); | |||
353 | if (pXFillStyleItem && pXFillStyleItem->GetValue() == drawing::FillStyle_SOLID && !rSet.HasItem(RES_BACKGROUND)) | |||
354 | { | |||
355 | // Construct an SvxBrushItem, as expected by the exporters. | |||
356 | std::unique_ptr<SvxBrushItem> aBrush(getSvxBrushItemFromSourceSet(rSet, RES_BACKGROUND)); | |||
357 | AttrOutput().OutputItem(*aBrush); | |||
358 | } | |||
359 | #if 0 | |||
360 | else | |||
361 | { | |||
362 | // note: *does not work* due to undocumented Word behavior: must be before a:ln element at least | |||
363 | AttrOutput().MaybeOutputBrushItem(rSet); | |||
364 | } | |||
365 | #endif | |||
366 | } | |||
367 | m_pISet = nullptr; // for double attributes | |||
368 | } | |||
369 | ||||
370 | void MSWordExportBase::GatherChapterFields() | |||
371 | { | |||
372 | //If the header/footer contains a chapter field | |||
373 | SwFieldType* pType = m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Chapter ); | |||
374 | pType->GatherNodeIndex(m_aChapterFieldLocs); | |||
375 | } | |||
376 | ||||
377 | bool MSWordExportBase::ContentContainsChapterField(const SwFormatContent &rContent) const | |||
378 | { | |||
379 | bool bRet = false; | |||
380 | if ( const SwNodeIndex* pSttIdx = rContent.GetContentIdx() ) | |||
381 | { | |||
382 | SwNodeIndex aIdx( *pSttIdx, 1 ); | |||
383 | SwNodeIndex aEnd( *pSttIdx->GetNode().EndOfSectionNode() ); | |||
384 | sal_uLong nStart = aIdx.GetIndex(); | |||
385 | sal_uLong nEnd = aEnd.GetIndex(); | |||
386 | //If the header/footer contains a chapter field | |||
387 | bRet = std::any_of(m_aChapterFieldLocs.cbegin(), m_aChapterFieldLocs.cend(), | |||
388 | [nStart, nEnd](sal_uLong i) { return ( nStart <= i ) && ( i <= nEnd ); }); | |||
389 | } | |||
390 | return bRet; | |||
391 | } | |||
392 | ||||
393 | bool MSWordExportBase::FormatHdFtContainsChapterField(const SwFrameFormat &rFormat) const | |||
394 | { | |||
395 | if ( m_aChapterFieldLocs.empty() ) | |||
396 | return false; | |||
397 | ||||
398 | const SwFrameFormat *pFormat = nullptr; | |||
399 | ||||
400 | pFormat = rFormat.GetHeader().GetHeaderFormat(); | |||
401 | if ( pFormat && ContentContainsChapterField( pFormat->GetContent() ) ) | |||
402 | return true; | |||
403 | ||||
404 | pFormat = rFormat.GetFooter().GetFooterFormat(); | |||
405 | return pFormat && ContentContainsChapterField( pFormat->GetContent() ); | |||
406 | } | |||
407 | ||||
408 | bool MSWordExportBase::SetCurrentPageDescFromNode(const SwNode &rNd) | |||
409 | { | |||
410 | bool bNewPageDesc = false; | |||
411 | const SwPageDesc* pCurrent = SwPageDesc::GetPageDescOfNode(rNd); | |||
412 | OSL_ENSURE(pCurrent && m_pCurrentPageDesc, "Not possible surely")do { if (true && (!(pCurrent && m_pCurrentPageDesc ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "412" ": "), "%s", "Not possible surely"); } } while (false ); | |||
413 | if (m_pCurrentPageDesc && pCurrent) | |||
414 | { | |||
415 | if (pCurrent != m_pCurrentPageDesc) | |||
416 | { | |||
417 | if (m_pCurrentPageDesc->GetFollow() != pCurrent) | |||
418 | bNewPageDesc = true; | |||
419 | else | |||
420 | { | |||
421 | const SwFrameFormat& rTitleFormat = m_pCurrentPageDesc->GetFirstMaster(); | |||
422 | const SwFrameFormat& rFollowFormat = pCurrent->GetMaster(); | |||
423 | ||||
424 | bNewPageDesc = !IsPlausableSingleWordSection(rTitleFormat, | |||
425 | rFollowFormat); | |||
426 | } | |||
427 | m_pCurrentPageDesc = pCurrent; | |||
428 | } | |||
429 | else | |||
430 | { | |||
431 | const SwFrameFormat &rFormat = pCurrent->GetMaster(); | |||
432 | bNewPageDesc = FormatHdFtContainsChapterField(rFormat); | |||
433 | } | |||
434 | } | |||
435 | return bNewPageDesc; | |||
436 | } | |||
437 | ||||
438 | /** | |||
439 | * WW only knows Break-After (page break and section breaks), | |||
440 | * whereas in SW page breaks exist both "before" and "after" and PageDesc exists | |||
441 | * only "before". Therefore the breaks are iterated two times, namely before | |||
442 | * and after every line. | |||
443 | * Depending on the break type they're set before or after the line. | |||
444 | * Only functions can be called, which do not write in output area pO, | |||
445 | * because that one only exits once for CHP and PAP and therefore end up in | |||
446 | * the wrong one. | |||
447 | */ | |||
448 | void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode& rNd, bool isCellOpen ) | |||
449 | { | |||
450 | if ( m_bStyDef || m_bOutKF || m_bInWriteEscher || m_bOutPageDescs ) | |||
| ||||
451 | return; | |||
452 | ||||
453 | m_bBreakBefore = true; | |||
454 | bool bNewPageDesc = false; | |||
455 | const SfxPoolItem* pItem=nullptr; | |||
456 | const SwFormatPageDesc *pPgDesc=nullptr; | |||
457 | ||||
458 | //Output a sectionbreak if there's a new pagedescriptor. Otherwise output a | |||
459 | //pagebreak if there is a pagebreak here, unless the new page (follow | |||
460 | //style) is different to the current one, in which case plump for a | |||
461 | //section. | |||
462 | bool bBreakSet = false; | |||
463 | ||||
464 | const SwPageDesc * pPageDesc = rNd.FindPageDesc(); | |||
465 | ||||
466 | // Even if m_pCurrentPageDesc != pPageDesc ,it might be because of the different header & footer types. | |||
467 | if (m_pCurrentPageDesc != pPageDesc) | |||
468 | { | |||
469 | if (isCellOpen && ( m_pCurrentPageDesc->GetName() != pPageDesc->GetName() )) | |||
470 | { | |||
471 | /* | |||
472 | * If Table cell is open and page header types are different | |||
473 | * set pSet to NULL as we don't want to add any section breaks inside a table. | |||
474 | */ | |||
475 | pSet = nullptr; | |||
476 | } | |||
477 | else if (!sw::util::IsPlausableSingleWordSection(m_pCurrentPageDesc->GetFirstMaster(), pPageDesc->GetMaster())) | |||
478 | { | |||
479 | bBreakSet = true; | |||
480 | bNewPageDesc = true; | |||
481 | m_pCurrentPageDesc = pPageDesc; | |||
482 | } | |||
483 | } | |||
484 | ||||
485 | if ( pSet && pSet->Count() ) | |||
486 | { | |||
487 | if ( SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem ) && | |||
488 | static_cast<const SwFormatPageDesc*>(pItem)->GetRegisteredIn() != nullptr) | |||
489 | { | |||
490 | bBreakSet = true; | |||
491 | bNewPageDesc = true; | |||
492 | pPgDesc = static_cast<const SwFormatPageDesc*>(pItem); | |||
493 | m_pCurrentPageDesc = pPgDesc->GetPageDesc(); | |||
494 | } | |||
495 | else if ( SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem ) ) | |||
496 | { | |||
497 | // Word does not like hard break attributes in some table cells | |||
498 | bool bRemoveHardBreakInsideTable = false; | |||
499 | if ( m_bOutTable ) | |||
500 | { | |||
501 | const SwTableNode* pTableNode = rNd.FindTableNode(); | |||
502 | if ( pTableNode ) | |||
503 | { | |||
504 | const SwTableBox* pBox = rNd.GetTableBox(); | |||
505 | const SwTableLine* pLine = pBox ? pBox->GetUpper() : nullptr; | |||
506 | // but only for non-complex tables | |||
507 | if ( pLine && !pLine->GetUpper() ) | |||
508 | { | |||
509 | // check if box is not first in that line: | |||
510 | if ( 0 < pLine->GetBoxPos( pBox ) && pBox->GetSttNd() ) | |||
511 | { | |||
512 | bRemoveHardBreakInsideTable = true; | |||
513 | } | |||
514 | } | |||
515 | } | |||
516 | } | |||
517 | bBreakSet = true; | |||
518 | ||||
519 | if ( !bRemoveHardBreakInsideTable
| |||
520 | { | |||
521 | OSL_ENSURE(m_pCurrentPageDesc, "should not be possible")do { if (true && (!(m_pCurrentPageDesc))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "521" ": "), "%s", "should not be possible"); } } while ( false); | |||
522 | /* | |||
523 | If because of this pagebreak the page desc following the page | |||
524 | break is the follow style of the current page desc then output a | |||
525 | section break using that style instead. At least in those cases | |||
526 | we end up with the same style in word and writer, nothing can be | |||
527 | done when it happens when we get a new pagedesc because we | |||
528 | overflow from the first page style. | |||
529 | */ | |||
530 | if ( m_pCurrentPageDesc
| |||
531 | { | |||
532 | // #i76301# - assure that there is a page break before set at the node. | |||
533 | const SvxFormatBreakItem* pBreak = dynamic_cast<const SvxFormatBreakItem*>(pItem); | |||
534 | if ( pBreak && | |||
535 | pBreak->GetBreak() == SvxBreak::PageBefore ) | |||
536 | { | |||
537 | bNewPageDesc |= SetCurrentPageDescFromNode( rNd ); | |||
538 | } | |||
539 | } | |||
540 | if ( !bNewPageDesc
| |||
541 | AttrOutput().OutputItem( *pItem ); | |||
| ||||
542 | } | |||
543 | } | |||
544 | } | |||
545 | ||||
546 | /* | |||
547 | #i9301# | |||
548 | No explicit page break, lets see if the style had one and we've moved to a | |||
549 | new page style because of it, if we have to then we take the opportunity to | |||
550 | set the equivalent word section here. We *could* do it for every paragraph | |||
551 | that moves onto a new page because of layout, but that would be insane. | |||
552 | */ | |||
553 | bool bHackInBreak = false; | |||
554 | if ( !bBreakSet ) | |||
555 | { | |||
556 | if ( const SwContentNode *pNd = rNd.GetContentNode() ) | |||
557 | { | |||
558 | const SvxFormatBreakItem &rBreak = | |||
559 | ItemGet<SvxFormatBreakItem>( *pNd, RES_BREAK ); | |||
560 | if ( rBreak.GetBreak() == SvxBreak::PageBefore ) | |||
561 | bHackInBreak = true; | |||
562 | else | |||
563 | { // Even a pagedesc item is set, the break item can be set 'NONE', | |||
564 | // but a pagedesc item is an implicit page break before... | |||
565 | const SwFormatPageDesc &rPageDesc = | |||
566 | ItemGet<SwFormatPageDesc>( *pNd, RES_PAGEDESC ); | |||
567 | if ( rPageDesc.KnowsPageDesc() ) | |||
568 | bHackInBreak = true; | |||
569 | } | |||
570 | } | |||
571 | } | |||
572 | ||||
573 | if ( bHackInBreak ) | |||
574 | { | |||
575 | OSL_ENSURE( m_pCurrentPageDesc, "should not be possible" )do { if (true && (!(m_pCurrentPageDesc))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "575" ": "), "%s", "should not be possible"); } } while ( false); | |||
576 | if ( m_pCurrentPageDesc ) | |||
577 | bNewPageDesc = SetCurrentPageDescFromNode( rNd ); | |||
578 | } | |||
579 | ||||
580 | if ( bNewPageDesc && m_pCurrentPageDesc ) | |||
581 | { | |||
582 | PrepareNewPageDesc( pSet, rNd, pPgDesc, m_pCurrentPageDesc ); | |||
583 | } | |||
584 | m_bBreakBefore = false; | |||
585 | } | |||
586 | ||||
587 | // #i76300# | |||
588 | bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTextNode* pNd ) | |||
589 | { | |||
590 | bool bRet = false; | |||
591 | ||||
592 | if ( pNd && | |||
593 | m_pCurrentPageDesc && | |||
594 | m_pCurrentPageDesc != m_pCurrentPageDesc->GetFollow() ) | |||
595 | { | |||
596 | PrepareNewPageDesc( pSet, *pNd, nullptr, m_pCurrentPageDesc->GetFollow() ); | |||
597 | bRet = true; | |||
598 | } | |||
599 | ||||
600 | return bRet; | |||
601 | } | |||
602 | ||||
603 | const SwSectionFormat* MSWordExportBase::GetSectionFormat( const SwNode& rNd ) | |||
604 | { | |||
605 | const SwSectionFormat* pFormat = nullptr; | |||
606 | const SwSectionNode* pSect = rNd.FindSectionNode(); | |||
607 | if ( pSect && | |||
608 | SectionType::Content == pSect->GetSection().GetType() ) | |||
609 | { | |||
610 | pFormat = pSect->GetSection().GetFormat(); | |||
611 | } | |||
612 | ||||
613 | return pFormat; | |||
614 | } | |||
615 | ||||
616 | sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNode& rNd ) | |||
617 | { | |||
618 | const SwFormatLineNumber* pNItem = nullptr; | |||
619 | if ( pSet ) | |||
620 | { | |||
621 | pNItem = &( ItemGet<SwFormatLineNumber>( *pSet, RES_LINENUMBER ) ); | |||
622 | } | |||
623 | else if ( const SwContentNode *pNd = rNd.GetContentNode() ) | |||
624 | { | |||
625 | pNItem = &( ItemGet<SwFormatLineNumber>( *pNd, RES_LINENUMBER ) ); | |||
626 | } | |||
627 | ||||
628 | return pNItem? pNItem->GetStartValue() : 0; | |||
629 | } | |||
630 | ||||
631 | void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet, | |||
632 | const SwNode& rNd, | |||
633 | const SwFormatPageDesc* pNewPgDescFormat, | |||
634 | const SwPageDesc* pNewPgDesc ) | |||
635 | { | |||
636 | // The PageDescs will only be inserted in WW8Writer::pSepx with the corresponding | |||
637 | // position by the occurrences of PageDesc attributes. The construction and | |||
638 | // output of the attributes and header/footer of the PageDesc are done | |||
639 | // after the main text and its attributes. | |||
640 | ||||
641 | sal_uLong nFcPos = ReplaceCr( msword::PageBreak ); // Page/Section-Break | |||
642 | ||||
643 | // actually nothing is outputted here, rather the arrays aCps, aSects | |||
644 | // accordingly completed | |||
645 | if ( !nFcPos ) | |||
646 | return; | |||
647 | ||||
648 | const SwSectionFormat* pFormat = GetSectionFormat( rNd ); | |||
649 | const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd ); | |||
650 | ||||
651 | OSL_ENSURE( pNewPgDescFormat || pNewPgDesc, "Neither page desc format nor page desc provided." )do { if (true && (!(pNewPgDescFormat || pNewPgDesc))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "651" ": "), "%s", "Neither page desc format nor page desc provided." ); } } while (false); | |||
652 | ||||
653 | if ( pNewPgDescFormat ) | |||
654 | { | |||
655 | pSepx->AppendSep( Fc2Cp( nFcPos ), *pNewPgDescFormat, rNd, pFormat, nLnNm ); | |||
656 | } | |||
657 | else if ( pNewPgDesc ) | |||
658 | { | |||
659 | pSepx->AppendSep( Fc2Cp( nFcPos ), pNewPgDesc, rNd, pFormat, nLnNm ); | |||
660 | } | |||
661 | } | |||
662 | ||||
663 | void MSWordExportBase::CorrectTabStopInSet( SfxItemSet& rSet, sal_Int32 nAbsLeft ) | |||
664 | { | |||
665 | const SvxTabStopItem *pItem = rSet.GetItem<SvxTabStopItem>(RES_PARATR_TABSTOP); | |||
666 | if (!pItem) | |||
667 | return; | |||
668 | ||||
669 | // then it must be corrected for the output | |||
670 | SvxTabStopItem aTStop(*pItem); | |||
671 | for ( sal_uInt16 nCnt = 0; nCnt < aTStop.Count(); ++nCnt ) | |||
672 | { | |||
673 | SvxTabStop& rTab = const_cast<SvxTabStop&>(aTStop[ nCnt ]); | |||
674 | if ( SvxTabAdjust::Default != rTab.GetAdjustment() && | |||
675 | rTab.GetTabPos() >= nAbsLeft ) | |||
676 | { | |||
677 | rTab.GetTabPos() -= nAbsLeft; | |||
678 | } | |||
679 | else | |||
680 | { | |||
681 | aTStop.Remove( nCnt ); | |||
682 | --nCnt; | |||
683 | } | |||
684 | } | |||
685 | rSet.Put( aTStop ); | |||
686 | } | |||
687 | ||||
688 | sal_uInt8 WW8Export::GetNumId( sal_uInt16 eNumType ) | |||
689 | { | |||
690 | sal_uInt8 nRet = 0; | |||
691 | switch( eNumType ) | |||
692 | { | |||
693 | case SVX_NUM_CHARS_UPPER_LETTER: | |||
694 | case SVX_NUM_CHARS_UPPER_LETTER_N: nRet = 3; break; | |||
695 | case SVX_NUM_CHARS_LOWER_LETTER: | |||
696 | case SVX_NUM_CHARS_LOWER_LETTER_N: nRet = 4; break; | |||
697 | case SVX_NUM_ROMAN_UPPER: nRet = 1; break; | |||
698 | case SVX_NUM_ROMAN_LOWER: nRet = 2; break; | |||
699 | ||||
700 | case SVX_NUM_BITMAP: | |||
701 | case SVX_NUM_CHAR_SPECIAL: nRet = 23; break; | |||
702 | ||||
703 | // nothing, WW does the same (undocumented) | |||
704 | case SVX_NUM_NUMBER_NONE: nRet = 0xff; break; | |||
705 | case SVX_NUM_SYMBOL_CHICAGO: | |||
706 | // 0x09, msonfcChiManSty | |||
707 | nRet = 9; | |||
708 | break; | |||
709 | case SVX_NUM_ARABIC_ZERO: | |||
710 | // 0x16, msonfcArabicLZ | |||
711 | nRet = 22; | |||
712 | break; | |||
713 | } | |||
714 | return nRet; | |||
715 | } | |||
716 | ||||
717 | void WW8AttributeOutput::OutlineNumbering(sal_uInt8 nLvl) | |||
718 | { | |||
719 | if ( nLvl >= WW8ListManager::nMaxLevel ) | |||
720 | nLvl = WW8ListManager::nMaxLevel-1; | |||
721 | ||||
722 | // write sprmPOutLvl sprmPIlvl and sprmPIlfo | |||
723 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::POutLvl::val ); | |||
724 | m_rWW8Export.pO->push_back( nLvl ); | |||
725 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::PIlvl::val ); | |||
726 | m_rWW8Export.pO->push_back( nLvl ); | |||
727 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::PIlfo::val ); | |||
728 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, | |||
729 | 1 + m_rWW8Export.GetNumberingId(*m_rWW8Export.m_rDoc.GetOutlineNumRule()) ); | |||
730 | } | |||
731 | ||||
732 | // #i77805# | |||
733 | bool WW8Export::DisallowInheritingOutlineNumbering(const SwFormat &rFormat) | |||
734 | { | |||
735 | bool bRet( false ); | |||
736 | ||||
737 | //If there is no numbering on this fmt, but its parent was outline | |||
738 | //numbered, then in writer this is no inheritied, but in word it would | |||
739 | //be, so we must export "no numbering" and "body level" to make word | |||
740 | //behave like writer (see #i25755) | |||
741 | if (SfxItemState::SET != rFormat.GetItemState(RES_PARATR_NUMRULE, false)) | |||
742 | { | |||
743 | if (const SwFormat *pParent = rFormat.DerivedFrom()) | |||
744 | { | |||
745 | if (static_cast<const SwTextFormatColl*>(pParent)->IsAssignedToListLevelOfOutlineStyle()) | |||
746 | { | |||
747 | SwWW8Writer::InsUInt16(*pO, NS_sprm::POutLvl::val); | |||
748 | pO->push_back(sal_uInt8(9)); | |||
749 | SwWW8Writer::InsUInt16(*pO, NS_sprm::PIlfo::val); | |||
750 | SwWW8Writer::InsUInt16(*pO, 0); | |||
751 | ||||
752 | bRet = true; | |||
753 | } | |||
754 | } | |||
755 | } | |||
756 | ||||
757 | return bRet; | |||
758 | } | |||
759 | ||||
760 | void MSWordExportBase::OutputFormat( const SwFormat& rFormat, bool bPapFormat, bool bChpFormat, bool bFlyFormat ) | |||
761 | { | |||
762 | bool bCallOutSet = true; | |||
763 | const SwModify* pOldMod = m_pOutFormatNode; | |||
764 | m_pOutFormatNode = &rFormat; | |||
765 | ||||
766 | switch( rFormat.Which() ) | |||
767 | { | |||
768 | case RES_CONDTXTFMTCOLL: | |||
769 | case RES_TXTFMTCOLL: | |||
770 | if( bPapFormat ) | |||
771 | { | |||
772 | int nLvl = MAXLEVEL; | |||
773 | ||||
774 | if (static_cast<const SwTextFormatColl&>(rFormat).IsAssignedToListLevelOfOutlineStyle()) | |||
775 | nLvl = static_cast<const SwTextFormatColl&>(rFormat).GetAssignedOutlineStyleLevel(); | |||
776 | ||||
777 | if (nLvl >= 0 && nLvl < MAXLEVEL) | |||
778 | { | |||
779 | //if outline numbered | |||
780 | // if Write StyleDefinition then write the OutlineRule | |||
781 | const SwNumFormat& rNFormat = m_rDoc.GetOutlineNumRule()->Get( static_cast<sal_uInt16>( nLvl ) ); | |||
782 | if ( m_bStyDef ) | |||
783 | AttrOutput().OutlineNumbering(static_cast<sal_uInt8>(nLvl)); | |||
784 | ||||
785 | if ( rNFormat.GetPositionAndSpaceMode() == | |||
786 | SvxNumberFormat::LABEL_WIDTH_AND_POSITION && | |||
787 | rNFormat.GetAbsLSpace() ) | |||
788 | { | |||
789 | SfxItemSet aSet( rFormat.GetAttrSet() ); | |||
790 | SvxLRSpaceItem aLR( | |||
791 | ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE)); | |||
792 | ||||
793 | aLR.SetTextLeft( aLR.GetTextLeft() + rNFormat.GetAbsLSpace() ); | |||
794 | aLR.SetTextFirstLineOffset( GetWordFirstLineOffset(rNFormat)); | |||
795 | ||||
796 | aSet.Put( aLR ); | |||
797 | CorrectTabStopInSet( aSet, rNFormat.GetAbsLSpace() ); | |||
798 | OutputItemSet( aSet, bPapFormat, bChpFormat, | |||
799 | i18n::ScriptType::LATIN, m_bExportModeRTF); | |||
800 | bCallOutSet = false; | |||
801 | } | |||
802 | } | |||
803 | else | |||
804 | { | |||
805 | //otherwise we might have to remove outline numbering from | |||
806 | //what gets exported if the parent style was outline numbered | |||
807 | // #i77805# | |||
808 | // If inherited outline numbering is suppress, the left/right | |||
809 | // margins has to be exported explicitly. | |||
810 | if ( m_bStyDef && DisallowInheritingOutlineNumbering(rFormat) ) | |||
811 | { | |||
812 | SfxItemSet aSet( rFormat.GetAttrSet() ); | |||
813 | const SvxLRSpaceItem& aLR( | |||
814 | ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE)); | |||
815 | aSet.Put( aLR ); | |||
816 | OutputItemSet( aSet, bPapFormat, bChpFormat, | |||
817 | css::i18n::ScriptType::LATIN, m_bExportModeRTF); | |||
818 | bCallOutSet = false; | |||
819 | } | |||
820 | } | |||
821 | } | |||
822 | break; | |||
823 | ||||
824 | case RES_CHRFMT: | |||
825 | break; | |||
826 | case RES_FLYFRMFMT: | |||
827 | if (bFlyFormat) | |||
828 | { | |||
829 | OSL_ENSURE(m_pParentFrame, "No parent frame, all broken")do { if (true && (!(m_pParentFrame))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "829" ": "), "%s", "No parent frame, all broken"); } } while (false); | |||
830 | ||||
831 | if (m_pParentFrame) | |||
832 | { | |||
833 | const SwFrameFormat &rFrameFormat = m_pParentFrame->GetFrameFormat(); | |||
834 | ||||
835 | SfxItemSet aSet(m_rDoc.GetAttrPool(), svl::Items<RES_FRMATR_BEGIN, | |||
836 | RES_FRMATR_END-1, | |||
837 | XATTR_FILL_FIRST, XATTR_FILL_LAST>{}); | |||
838 | aSet.Set(rFrameFormat.GetAttrSet()); | |||
839 | ||||
840 | // Fly as character becomes a paragraph bound | |||
841 | // now set the distance to paragraph margin | |||
842 | if (m_pFlyOffset) | |||
843 | { | |||
844 | aSet.Put(SwFormatHoriOrient(m_pFlyOffset->X())); | |||
845 | aSet.Put(SwFormatVertOrient(m_pFlyOffset->Y())); | |||
846 | SwFormatAnchor aAnchor(rFrameFormat.GetAnchor()); | |||
847 | aAnchor.SetType(m_eNewAnchorType); | |||
848 | aSet.Put(aAnchor); | |||
849 | } | |||
850 | ||||
851 | if (SfxItemState::SET != aSet.GetItemState(RES_SURROUND)) | |||
852 | aSet.Put(SwFormatSurround(css::text::WrapTextMode_NONE)); | |||
853 | ||||
854 | const XFillStyleItem* pXFillStyleItem(rFrameFormat.GetAttrSet().GetItem<XFillStyleItem>(XATTR_FILLSTYLE)); | |||
855 | if (pXFillStyleItem) | |||
856 | { | |||
857 | switch (pXFillStyleItem->GetValue()) | |||
858 | { | |||
859 | case drawing::FillStyle_NONE: | |||
860 | break; | |||
861 | case drawing::FillStyle_SOLID: | |||
862 | { | |||
863 | // Construct an SvxBrushItem, as expected by the exporters. | |||
864 | std::unique_ptr<SvxBrushItem> aBrush(getSvxBrushItemFromSourceSet(rFrameFormat.GetAttrSet(), RES_BACKGROUND)); | |||
865 | aSet.Put(*aBrush); | |||
866 | break; | |||
867 | } | |||
868 | default: | |||
869 | break; | |||
870 | } | |||
871 | } | |||
872 | ||||
873 | m_bOutFlyFrameAttrs = true; | |||
874 | //script doesn't matter if not exporting chp | |||
875 | OutputItemSet(aSet, true, false, | |||
876 | i18n::ScriptType::LATIN, m_bExportModeRTF); | |||
877 | m_bOutFlyFrameAttrs = false; | |||
878 | ||||
879 | bCallOutSet = false; | |||
880 | } | |||
881 | } | |||
882 | break; | |||
883 | case RES_FRMFMT: | |||
884 | break; | |||
885 | default: | |||
886 | OSL_ENSURE( false, "Which format is exported here?" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "886" ": "), "%s", "Which format is exported here?"); } } while (false); | |||
887 | break; | |||
888 | } | |||
889 | ||||
890 | if( bCallOutSet ) | |||
891 | OutputItemSet( rFormat.GetAttrSet(), bPapFormat, bChpFormat, | |||
892 | i18n::ScriptType::LATIN, m_bExportModeRTF); | |||
893 | m_pOutFormatNode = pOldMod; | |||
894 | } | |||
895 | ||||
896 | bool MSWordExportBase::HasRefToAttr(const OUString& rName) | |||
897 | { | |||
898 | SwFieldType* pType = m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetRef); | |||
899 | std::vector<SwGetRefField*> vpRFields; | |||
900 | pType->GatherRefFields(vpRFields, REF_SETREFATTR); | |||
901 | return std::any_of(vpRFields.begin(), vpRFields.end(), | |||
902 | [rName](SwGetRefField* pF) { return rName == pF->GetSetRefName(); }); | |||
903 | } | |||
904 | ||||
905 | bool MSWordExportBase::HasRefToFootOrEndnote(const bool isEndNote, const sal_uInt16 nSeqNo) | |||
906 | { | |||
907 | SwFieldType* pType = m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetRef); | |||
908 | std::vector<SwGetRefField*> vpRFields; | |||
909 | pType->GatherRefFields(vpRFields, isEndNote ? REF_ENDNOTE : REF_FOOTNOTE); | |||
910 | return std::any_of(vpRFields.begin(), vpRFields.end(), | |||
911 | [nSeqNo](SwGetRefField* pF) { return nSeqNo == pF->GetSeqNo(); }); | |||
912 | } | |||
913 | ||||
914 | OUString MSWordExportBase::GetBookmarkName( sal_uInt16 nTyp, const OUString* pName, sal_uInt16 nSeqNo ) | |||
915 | { | |||
916 | OUString sRet; | |||
917 | switch ( nTyp ) | |||
918 | { | |||
919 | case REF_SETREFATTR: | |||
920 | if ( pName ) | |||
921 | { | |||
922 | sRet = "Ref_" + *pName; | |||
923 | } | |||
924 | break; | |||
925 | case REF_SEQUENCEFLD: | |||
926 | { | |||
927 | assert(pName)(static_cast <bool> (pName) ? void (0) : __assert_fail ( "pName", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 927, __extension__ __PRETTY_FUNCTION__)); | |||
928 | sRet = "Ref_" + *pName; | |||
929 | break; | |||
930 | } | |||
931 | case REF_BOOKMARK: | |||
932 | if ( pName ) | |||
933 | sRet = *pName; | |||
934 | break; | |||
935 | case REF_OUTLINE: | |||
936 | break; // ??? | |||
937 | case REF_FOOTNOTE: | |||
938 | sRet = "_RefF" + OUString::number( nSeqNo ); | |||
939 | break; | |||
940 | case REF_ENDNOTE: | |||
941 | sRet = "_RefE" + OUString::number( nSeqNo ); | |||
942 | break; | |||
943 | } | |||
944 | return BookmarkToWord( sRet ); // #i43956# - encode bookmark accordingly | |||
945 | } | |||
946 | ||||
947 | /* File CHRATR.HXX: */ | |||
948 | void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript ) | |||
949 | { | |||
950 | if (bIsRTL) | |||
951 | { | |||
952 | if( m_rWW8Export.m_rDoc.GetDocumentType() != SwDoc::DOCTYPE_MSWORD ) | |||
953 | { | |||
954 | m_rWW8Export.InsUInt16( NS_sprm::CFBiDi::val ); | |||
955 | m_rWW8Export.pO->push_back( sal_uInt8(1) ); | |||
956 | } | |||
957 | } | |||
958 | ||||
959 | // #i46087# patch from james_clark; complex texts needs the undocumented SPRM CComplexScript with param 0x81. | |||
960 | if (nScript == i18n::ScriptType::COMPLEX && !bIsRTL) | |||
961 | { | |||
962 | m_rWW8Export.InsUInt16( NS_sprm::CFComplexScripts::val ); | |||
963 | m_rWW8Export.pO->push_back( sal_uInt8(0x81) ); | |||
964 | m_rWW8Export.pDop->bUseThaiLineBreakingRules = true; | |||
965 | } | |||
966 | } | |||
967 | ||||
968 | void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) | |||
969 | { | |||
970 | m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() - (mbOnTOXEnding?2:0), m_rWW8Export.pO->size(), m_rWW8Export.pO->data() ); | |||
971 | mbOnTOXEnding = false; | |||
972 | m_rWW8Export.pO->clear(); | |||
973 | ||||
974 | if ( pTextNodeInfoInner ) | |||
975 | { | |||
976 | if ( pTextNodeInfoInner->isEndOfLine() ) | |||
977 | { | |||
978 | TableRowEnd( pTextNodeInfoInner->getDepth() ); | |||
979 | ||||
980 | SVBT16 nSty; | |||
981 | ShortToSVBT16( 0, nSty ); | |||
982 | m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nSty, nSty+2 ); // Style # | |||
983 | TableInfoRow( pTextNodeInfoInner ); | |||
984 | m_rWW8Export.m_pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->size(), m_rWW8Export.pO->data()); | |||
985 | m_rWW8Export.pO->clear(); | |||
986 | } | |||
987 | } | |||
988 | ||||
989 | // Clear bookmarks of the current paragraph | |||
990 | m_aBookmarksOfParagraphStart.clear(); | |||
991 | m_aBookmarksOfParagraphEnd.clear(); | |||
992 | } | |||
993 | ||||
994 | void WW8AttributeOutput::StartRunProperties() | |||
995 | { | |||
996 | WW8_WrPlcField* pCurrentFields = m_rWW8Export.CurrentFieldPlc(); | |||
997 | m_nFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0; | |||
998 | } | |||
999 | ||||
1000 | void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData, sal_Int32 nPos, bool /*bSingleEmptyRun*/ ) | |||
1001 | { | |||
1002 | if (pRedlineData) | |||
1003 | { | |||
1004 | const OUString &rComment = pRedlineData->GetComment(); | |||
1005 | //Only possible to export to main text | |||
1006 | if (!rComment.isEmpty() && (m_rWW8Export.m_nTextTyp == TXT_MAINTEXT)) | |||
1007 | { | |||
1008 | if (m_rWW8Export.m_pAtn->IsNewRedlineComment(pRedlineData)) | |||
1009 | { | |||
1010 | m_rWW8Export.m_pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pRedlineData ); | |||
1011 | m_rWW8Export.WritePostItBegin( m_rWW8Export.pO.get() ); | |||
1012 | } | |||
1013 | } | |||
1014 | } | |||
1015 | ||||
1016 | /// Insert bookmarks started at this run | |||
1017 | auto aRange = m_aBookmarksOfParagraphStart.equal_range(nPos); | |||
1018 | for( auto aIter = aRange.first; aIter != aRange.second; ++aIter) | |||
1019 | { | |||
1020 | GetExport().AppendBookmark(BookmarkToWord(aIter->second)); | |||
1021 | } | |||
1022 | } | |||
1023 | ||||
1024 | void WW8AttributeOutput::OnTOXEnding() | |||
1025 | { | |||
1026 | mbOnTOXEnding = true; | |||
1027 | } | |||
1028 | ||||
1029 | void WW8AttributeOutput::EndRun( const SwTextNode* /*pNode*/, sal_Int32 nPos, bool bLastRun ) | |||
1030 | { | |||
1031 | /// Insert bookmarks ended after this run | |||
1032 | auto aRange = m_aBookmarksOfParagraphEnd.equal_range(nPos); | |||
1033 | for( auto aIter = aRange.first; aIter != aRange.second; ++aIter) | |||
1034 | { | |||
1035 | if(bLastRun) | |||
1036 | GetExport().AppendBookmarkEndWithCorrection(BookmarkToWord(aIter->second)); | |||
1037 | else | |||
1038 | GetExport().AppendBookmark(BookmarkToWord(aIter->second)); | |||
1039 | } | |||
1040 | } | |||
1041 | ||||
1042 | void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData ) | |||
1043 | { | |||
1044 | Redline( pRedlineData ); | |||
1045 | ||||
1046 | WW8_WrPlcField* pCurrentFields = m_rWW8Export.CurrentFieldPlc(); | |||
1047 | sal_uInt16 nNewFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0; | |||
1048 | ||||
1049 | bool bExportedFieldResult = ( m_nFieldResults != nNewFieldResults ); | |||
1050 | ||||
1051 | // If we have exported a field result, then we will have been forced to | |||
1052 | // split up the text into a 0x13, 0x14, <result> 0x15 sequence with the | |||
1053 | // properties forced out at the end of the result, so the 0x15 itself | |||
1054 | // should remain clean of all other attributes to avoid #iXXXXX# | |||
1055 | if ( !bExportedFieldResult ) | |||
1056 | { | |||
1057 | m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), | |||
1058 | m_rWW8Export.pO->size(), m_rWW8Export.pO->data() ); | |||
1059 | } | |||
1060 | m_rWW8Export.pO->clear(); | |||
1061 | } | |||
1062 | ||||
1063 | void WW8AttributeOutput::RunText( const OUString& rText, rtl_TextEncoding eCharSet ) | |||
1064 | { | |||
1065 | RawText(rText, eCharSet); | |||
1066 | } | |||
1067 | ||||
1068 | void WW8AttributeOutput::RawText(const OUString& rText, rtl_TextEncoding) | |||
1069 | { | |||
1070 | m_rWW8Export.OutSwString(rText, 0, rText.getLength()); | |||
1071 | } | |||
1072 | ||||
1073 | void WW8AttributeOutput::OutputFKP(bool bForce) | |||
1074 | { | |||
1075 | if (!m_rWW8Export.pO->empty() || bForce) | |||
1076 | { | |||
1077 | m_rWW8Export.m_pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), | |||
1078 | m_rWW8Export.pO->size(), m_rWW8Export.pO->data() ); | |||
1079 | m_rWW8Export.pO->clear(); | |||
1080 | } | |||
1081 | } | |||
1082 | ||||
1083 | void WW8AttributeOutput::ParagraphStyle( sal_uInt16 nStyle ) | |||
1084 | { | |||
1085 | OSL_ENSURE( m_rWW8Export.pO->empty(), " pO is not empty at line end" )do { if (true && (!(m_rWW8Export.pO->empty()))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "1085" ": "), "%s", " pO is not empty at line end"); } } while (false); | |||
1086 | ||||
1087 | SVBT16 nSty; | |||
1088 | ShortToSVBT16( nStyle, nSty ); | |||
1089 | m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), nSty, nSty+2 ); // style # | |||
1090 | } | |||
1091 | ||||
1092 | void WW8AttributeOutput::OutputWW8Attribute( sal_uInt8 nId, bool bVal ) | |||
1093 | { | |||
1094 | m_rWW8Export.InsUInt16( 8 == nId ? NS_sprm::CFDStrike::val : NS_sprm::CFBold::val + nId ); | |||
1095 | ||||
1096 | m_rWW8Export.pO->push_back( bVal ? 1 : 0 ); | |||
1097 | } | |||
1098 | ||||
1099 | void WW8AttributeOutput::OutputWW8AttributeCTL( sal_uInt8 nId, bool bVal ) | |||
1100 | { | |||
1101 | OSL_ENSURE( nId <= 1, "out of range" )do { if (true && (!(nId <= 1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "1101" ": "), "%s", "out of range"); } } while (false); | |||
1102 | if (nId > 1) | |||
1103 | return; | |||
1104 | ||||
1105 | m_rWW8Export.InsUInt16( NS_sprm::CFBoldBi::val + nId ); | |||
1106 | m_rWW8Export.pO->push_back( bVal ? 1 : 0 ); | |||
1107 | } | |||
1108 | ||||
1109 | void WW8AttributeOutput::CharFont( const SvxFontItem& rFont ) | |||
1110 | { | |||
1111 | sal_uInt16 nFontID = m_rWW8Export.GetId( rFont ); | |||
1112 | ||||
1113 | m_rWW8Export.InsUInt16( NS_sprm::CRgFtc0::val ); | |||
1114 | m_rWW8Export.InsUInt16( nFontID ); | |||
1115 | m_rWW8Export.InsUInt16( NS_sprm::CRgFtc2::val ); | |||
1116 | ||||
1117 | m_rWW8Export.InsUInt16( nFontID ); | |||
1118 | } | |||
1119 | ||||
1120 | void WW8AttributeOutput::CharFontCTL( const SvxFontItem& rFont ) | |||
1121 | { | |||
1122 | sal_uInt16 nFontID = m_rWW8Export.GetId( rFont ); | |||
1123 | m_rWW8Export.InsUInt16( NS_sprm::CFtcBi::val ); | |||
1124 | m_rWW8Export.InsUInt16( nFontID ); | |||
1125 | } | |||
1126 | ||||
1127 | void WW8AttributeOutput::CharFontCJK( const SvxFontItem& rFont ) | |||
1128 | { | |||
1129 | sal_uInt16 nFontID = m_rWW8Export.GetId( rFont ); | |||
1130 | m_rWW8Export.InsUInt16( NS_sprm::CRgFtc1::val ); | |||
1131 | m_rWW8Export.InsUInt16( nFontID ); | |||
1132 | } | |||
1133 | ||||
1134 | void WW8AttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight ) | |||
1135 | { | |||
1136 | OutputWW8AttributeCTL( 0, WEIGHT_BOLD == rWeight.GetWeight()); | |||
1137 | } | |||
1138 | ||||
1139 | void WW8AttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture ) | |||
1140 | { | |||
1141 | OutputWW8AttributeCTL( 1, ITALIC_NONE != rPosture.GetPosture() ); | |||
1142 | } | |||
1143 | ||||
1144 | void WW8AttributeOutput::CharPosture( const SvxPostureItem& rPosture ) | |||
1145 | { | |||
1146 | OutputWW8Attribute( 1, ITALIC_NONE != rPosture.GetPosture() ); | |||
1147 | } | |||
1148 | ||||
1149 | void WW8AttributeOutput::CharWeight( const SvxWeightItem& rWeight ) | |||
1150 | { | |||
1151 | OutputWW8Attribute( 0, WEIGHT_BOLD == rWeight.GetWeight() ); | |||
1152 | } | |||
1153 | ||||
1154 | // Shadowed and Contour are not in WW-UI. JP: ?? | |||
1155 | void WW8AttributeOutput::CharContour( const SvxContourItem& rContour ) | |||
1156 | { | |||
1157 | OutputWW8Attribute( 3, rContour.GetValue() ); | |||
1158 | } | |||
1159 | ||||
1160 | void WW8AttributeOutput::CharShadow( const SvxShadowedItem& rShadow ) | |||
1161 | { | |||
1162 | OutputWW8Attribute( 4, rShadow.GetValue() ); | |||
1163 | } | |||
1164 | ||||
1165 | void WW8AttributeOutput::CharKerning( const SvxKerningItem& rKerning ) | |||
1166 | { | |||
1167 | m_rWW8Export.InsUInt16( NS_sprm::CDxaSpace::val ); | |||
1168 | ||||
1169 | m_rWW8Export.InsUInt16( rKerning.GetValue() ); | |||
1170 | } | |||
1171 | ||||
1172 | void WW8AttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern ) | |||
1173 | { | |||
1174 | m_rWW8Export.InsUInt16( NS_sprm::CHpsKern::val ); | |||
1175 | ||||
1176 | m_rWW8Export.InsUInt16( rAutoKern.GetValue() ? 2 : 0 ); | |||
1177 | } | |||
1178 | ||||
1179 | void WW8AttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink ) | |||
1180 | { | |||
1181 | m_rWW8Export.InsUInt16( NS_sprm::CSfxText::val ); | |||
1182 | // At the moment the only animated text effect we support is blinking | |||
1183 | m_rWW8Export.pO->push_back( rBlink.GetValue() ? 2 : 0 ); | |||
1184 | } | |||
1185 | ||||
1186 | void WW8AttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossed ) | |||
1187 | { | |||
1188 | FontStrikeout eSt = rCrossed.GetStrikeout(); | |||
1189 | if ( STRIKEOUT_DOUBLE == eSt ) | |||
1190 | { | |||
1191 | OutputWW8Attribute( 8, true ); | |||
1192 | return; | |||
1193 | } | |||
1194 | if ( STRIKEOUT_NONE != eSt ) | |||
1195 | { | |||
1196 | OutputWW8Attribute( 2, true ); | |||
1197 | return; | |||
1198 | } | |||
1199 | ||||
1200 | // otherwise both off | |||
1201 | OutputWW8Attribute( 8, false ); | |||
1202 | OutputWW8Attribute( 2, false ); | |||
1203 | } | |||
1204 | ||||
1205 | void WW8AttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap ) | |||
1206 | { | |||
1207 | SvxCaseMap eSt = rCaseMap.GetValue(); | |||
1208 | switch ( eSt ) | |||
1209 | { | |||
1210 | case SvxCaseMap::SmallCaps: | |||
1211 | OutputWW8Attribute( 5, true ); | |||
1212 | return; | |||
1213 | case SvxCaseMap::Uppercase: | |||
1214 | OutputWW8Attribute( 6, true ); | |||
1215 | return; | |||
1216 | case SvxCaseMap::Capitalize: | |||
1217 | // no such feature in word | |||
1218 | break; | |||
1219 | default: | |||
1220 | // otherwise both off | |||
1221 | OutputWW8Attribute( 5, false ); | |||
1222 | OutputWW8Attribute( 6, false ); | |||
1223 | return; | |||
1224 | } | |||
1225 | } | |||
1226 | ||||
1227 | void WW8AttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden ) | |||
1228 | { | |||
1229 | OutputWW8Attribute( 7, rHidden.GetValue() ); | |||
1230 | } | |||
1231 | ||||
1232 | void WW8AttributeOutput::CharBorder( const SvxBorderLine* pAllBorder, const sal_uInt16 /*nDist*/, const bool bShadow ) | |||
1233 | { | |||
1234 | WW8Export::Out_BorderLine( *m_rWW8Export.pO, pAllBorder, 0, NS_sprm::CBrc80::val, NS_sprm::CBrc::val, bShadow ); | |||
1235 | } | |||
1236 | ||||
1237 | void WW8AttributeOutput::CharHighlight( const SvxBrushItem& rBrush ) | |||
1238 | { | |||
1239 | if (rBrush.GetColor() != COL_TRANSPARENT) | |||
1240 | { | |||
1241 | sal_uInt8 nColor = msfilter::util::TransColToIco( rBrush.GetColor() ); | |||
1242 | // sprmCHighlight | |||
1243 | m_rWW8Export.InsUInt16( NS_sprm::CHighlight::val ); | |||
1244 | m_rWW8Export.pO->push_back( nColor ); | |||
1245 | } | |||
1246 | } | |||
1247 | ||||
1248 | void WW8AttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline ) | |||
1249 | { | |||
1250 | m_rWW8Export.InsUInt16( NS_sprm::CKul::val ); | |||
1251 | ||||
1252 | const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_CHRATR_WORDLINEMODE ); | |||
1253 | bool bWord = false; | |||
1254 | if (pItem) | |||
1255 | bWord = static_cast<const SvxWordLineModeItem*>(pItem)->GetValue(); | |||
1256 | ||||
1257 | // WW95 - parameters: 0 = none, 1 = single, 2 = by Word, | |||
1258 | // 3 = double, 4 = dotted, 5 = hidden | |||
1259 | // WW97 - additional parameters: | |||
1260 | // 6 = thick, 7 = dash, 8 = dot(not used) | |||
1261 | // 9 = dotdash 10 = dotdotdash, 11 = wave | |||
1262 | sal_uInt8 b = 0; | |||
1263 | switch ( rUnderline.GetLineStyle() ) | |||
1264 | { | |||
1265 | case LINESTYLE_SINGLE: | |||
1266 | b = bWord ? 2 : 1; | |||
1267 | break; | |||
1268 | case LINESTYLE_BOLD: | |||
1269 | b = 6; | |||
1270 | break; | |||
1271 | case LINESTYLE_DOUBLE: | |||
1272 | b = 3; | |||
1273 | break; | |||
1274 | case LINESTYLE_DOTTED: | |||
1275 | b = 4; | |||
1276 | break; | |||
1277 | case LINESTYLE_DASH: | |||
1278 | b = 7; | |||
1279 | break; | |||
1280 | case LINESTYLE_DASHDOT: | |||
1281 | b = 9; | |||
1282 | break; | |||
1283 | case LINESTYLE_DASHDOTDOT: | |||
1284 | b = 10; | |||
1285 | break; | |||
1286 | case LINESTYLE_WAVE: | |||
1287 | b = 11; | |||
1288 | break; | |||
1289 | // new in WW2000 | |||
1290 | case LINESTYLE_BOLDDOTTED: | |||
1291 | b = 20; | |||
1292 | break; | |||
1293 | case LINESTYLE_BOLDDASH: | |||
1294 | b = 23; | |||
1295 | break; | |||
1296 | case LINESTYLE_LONGDASH: | |||
1297 | b = 39; | |||
1298 | break; | |||
1299 | case LINESTYLE_BOLDLONGDASH: | |||
1300 | b = 55; | |||
1301 | break; | |||
1302 | case LINESTYLE_BOLDDASHDOT: | |||
1303 | b = 25; | |||
1304 | break; | |||
1305 | case LINESTYLE_BOLDDASHDOTDOT: | |||
1306 | b = 26; | |||
1307 | break; | |||
1308 | case LINESTYLE_BOLDWAVE: | |||
1309 | b = 27; | |||
1310 | break; | |||
1311 | case LINESTYLE_DOUBLEWAVE: | |||
1312 | b = 43; | |||
1313 | break; | |||
1314 | case LINESTYLE_NONE: | |||
1315 | b = 0; | |||
1316 | break; | |||
1317 | default: | |||
1318 | OSL_ENSURE( rUnderline.GetLineStyle() == LINESTYLE_NONE, "Unhandled underline type" )do { if (true && (!(rUnderline.GetLineStyle() == LINESTYLE_NONE ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "1318" ": "), "%s", "Unhandled underline type"); } } while (false); | |||
1319 | break; | |||
1320 | } | |||
1321 | ||||
1322 | m_rWW8Export.pO->push_back( b ); | |||
1323 | Color aColor = rUnderline.GetColor(); | |||
1324 | if( aColor != COL_TRANSPARENT ) | |||
1325 | { | |||
1326 | m_rWW8Export.InsUInt16( NS_sprm::CCvUl::val ); | |||
1327 | ||||
1328 | m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( aColor ) ); | |||
1329 | } | |||
1330 | } | |||
1331 | ||||
1332 | void WW8AttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage ) | |||
1333 | { | |||
1334 | sal_uInt16 nId = 0; | |||
1335 | switch ( rLanguage.Which() ) | |||
1336 | { | |||
1337 | case RES_CHRATR_LANGUAGE: | |||
1338 | nId = NS_sprm::CRgLid0_80::val; | |||
1339 | break; | |||
1340 | case RES_CHRATR_CJK_LANGUAGE: | |||
1341 | nId = NS_sprm::CRgLid1_80::val; | |||
1342 | break; | |||
1343 | case RES_CHRATR_CTL_LANGUAGE: | |||
1344 | nId = NS_sprm::CLidBi::val; | |||
1345 | break; | |||
1346 | } | |||
1347 | ||||
1348 | if ( !nId ) | |||
1349 | return; | |||
1350 | ||||
1351 | // use sprmCRgLid0_80 rather than sprmCLid | |||
1352 | m_rWW8Export.InsUInt16( nId ); | |||
1353 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(rLanguage.GetLanguage()) ); | |||
1354 | ||||
1355 | // Word 2000 and above apparently require both old and new versions of | |||
1356 | // these sprms to be set, without it spellchecking doesn't work | |||
1357 | if ( nId == NS_sprm::CRgLid0_80::val ) | |||
1358 | { | |||
1359 | m_rWW8Export.InsUInt16( NS_sprm::CRgLid0::val ); | |||
1360 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(rLanguage.GetLanguage()) ); | |||
1361 | } | |||
1362 | else if ( nId == NS_sprm::CRgLid1_80::val ) | |||
1363 | { | |||
1364 | m_rWW8Export.InsUInt16( NS_sprm::CRgLid1::val ); | |||
1365 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(rLanguage.GetLanguage()) ); | |||
1366 | } | |||
1367 | } | |||
1368 | ||||
1369 | void WW8AttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement ) | |||
1370 | { | |||
1371 | sal_uInt8 b = 0xFF; | |||
1372 | short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProportionalHeight(); | |||
1373 | if ( !nEsc ) | |||
1374 | { | |||
1375 | b = 0; | |||
1376 | nEsc = 0; | |||
1377 | nProp = 100; | |||
1378 | } | |||
1379 | else if ( DFLT_ESC_PROP58 == nProp || nProp < 1 || nProp > 100 ) | |||
1380 | { | |||
1381 | if ( DFLT_ESC_SUB-8 == nEsc || DFLT_ESC_AUTO_SUB-(13999 +1) == nEsc ) | |||
1382 | b = 2; | |||
1383 | else if ( DFLT_ESC_SUPER33 == nEsc || DFLT_ESC_AUTO_SUPER(13999 +1) == nEsc ) | |||
1384 | b = 1; | |||
1385 | } | |||
1386 | else if ( DFLT_ESC_AUTO_SUPER(13999 +1) == nEsc ) | |||
1387 | { | |||
1388 | // Raised by the differences between the ascenders (ascent = baseline to top of highest letter). | |||
1389 | // The ascent is generally about 80% of the total font height. | |||
1390 | // That is why DFLT_ESC_PROP (58) leads to 33% (DFLT_ESC_SUPER) | |||
1391 | nEsc = .8 * (100 - nProp); | |||
1392 | } | |||
1393 | else if ( DFLT_ESC_AUTO_SUB-(13999 +1) == nEsc ) | |||
1394 | { | |||
1395 | // Lowered by the differences between the descenders (descent = baseline to bottom of lowest letter). | |||
1396 | // The descent is generally about 20% of the total font height. | |||
1397 | // That is why DFLT_ESC_PROP (58) leads to 8% (DFLT_ESC_SUB) | |||
1398 | nEsc = .2 * -(100 - nProp); | |||
1399 | } | |||
1400 | ||||
1401 | if ( 0xFF != b ) | |||
1402 | { | |||
1403 | m_rWW8Export.InsUInt16( NS_sprm::CIss::val ); | |||
1404 | ||||
1405 | m_rWW8Export.pO->push_back( b ); | |||
1406 | } | |||
1407 | ||||
1408 | if ( 0 != b && 0xFF != b ) | |||
1409 | return; | |||
1410 | ||||
1411 | double fHeight = m_rWW8Export.GetItem( RES_CHRATR_FONTSIZE ).GetHeight(); | |||
1412 | m_rWW8Export.InsUInt16( NS_sprm::CHpsPos::val ); | |||
1413 | ||||
1414 | m_rWW8Export.InsUInt16(static_cast<short>( round(fHeight * nEsc / 1000) )); | |||
1415 | ||||
1416 | if( 100 != nProp || !b ) | |||
1417 | { | |||
1418 | m_rWW8Export.InsUInt16( NS_sprm::CHps::val ); | |||
1419 | m_rWW8Export.InsUInt16(msword_cast<sal_uInt16>( round(fHeight * nProp / 1000) )); | |||
1420 | } | |||
1421 | } | |||
1422 | ||||
1423 | void WW8AttributeOutput::CharFontSize( const SvxFontHeightItem& rHeight ) | |||
1424 | { | |||
1425 | sal_uInt16 nId = 0; | |||
1426 | switch ( rHeight.Which() ) | |||
1427 | { | |||
1428 | case RES_CHRATR_FONTSIZE: | |||
1429 | case RES_CHRATR_CJK_FONTSIZE: | |||
1430 | nId = NS_sprm::CHps::val; | |||
1431 | break; | |||
1432 | case RES_CHRATR_CTL_FONTSIZE: | |||
1433 | nId = NS_sprm::CHpsBi::val; | |||
1434 | break; | |||
1435 | } | |||
1436 | ||||
1437 | if ( nId ) | |||
1438 | { | |||
1439 | m_rWW8Export.InsUInt16( nId ); | |||
1440 | ||||
1441 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(( rHeight.GetHeight() + 5 ) / 10 ) ); | |||
1442 | } | |||
1443 | } | |||
1444 | ||||
1445 | void WW8AttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth ) | |||
1446 | { | |||
1447 | m_rWW8Export.InsUInt16( NS_sprm::CCharScale::val ); | |||
1448 | m_rWW8Export.InsUInt16( rScaleWidth.GetValue() ); | |||
1449 | } | |||
1450 | ||||
1451 | void WW8AttributeOutput::CharRelief( const SvxCharReliefItem& rRelief ) | |||
1452 | { | |||
1453 | sal_uInt16 nId; | |||
1454 | switch ( rRelief.GetValue() ) | |||
1455 | { | |||
1456 | case FontRelief::Embossed: nId = NS_sprm::CFEmboss::val; break; | |||
1457 | case FontRelief::Engraved: nId = NS_sprm::CFImprint::val; break; | |||
1458 | default: nId = 0; break; | |||
1459 | } | |||
1460 | ||||
1461 | if( nId ) | |||
1462 | { | |||
1463 | m_rWW8Export.InsUInt16( nId ); | |||
1464 | m_rWW8Export.pO->push_back( sal_uInt8(0x81) ); | |||
1465 | } | |||
1466 | else | |||
1467 | { | |||
1468 | // switch both flags off | |||
1469 | m_rWW8Export.InsUInt16( NS_sprm::CFEmboss::val ); | |||
1470 | m_rWW8Export.pO->push_back( sal_uInt8(0x0) ); | |||
1471 | m_rWW8Export.InsUInt16( NS_sprm::CFImprint::val ); | |||
1472 | m_rWW8Export.pO->push_back( sal_uInt8(0x0) ); | |||
1473 | } | |||
1474 | } | |||
1475 | ||||
1476 | void WW8AttributeOutput::CharBidiRTL( const SfxPoolItem& rHt ) | |||
1477 | { | |||
1478 | const SfxInt16Item& rAttr = static_cast<const SfxInt16Item&>(rHt); | |||
1479 | if( rAttr.GetValue() == 1 ) | |||
1480 | { | |||
1481 | m_rWW8Export.InsUInt16(0x85a); | |||
1482 | m_rWW8Export.pO->push_back(sal_uInt8(1)); | |||
1483 | } | |||
1484 | } | |||
1485 | ||||
1486 | void WW8AttributeOutput::CharIdctHint( const SfxPoolItem& rHt ) | |||
1487 | { | |||
1488 | const SfxInt16Item& rAttr = static_cast<const SfxInt16Item&>(rHt); | |||
1489 | m_rWW8Export.InsUInt16(0x286F); | |||
1490 | m_rWW8Export.pO->push_back(static_cast<sal_uInt8>(rAttr.GetValue())); | |||
1491 | } | |||
1492 | ||||
1493 | void WW8AttributeOutput::CharRotate( const SvxCharRotateItem& rRotate ) | |||
1494 | { | |||
1495 | // #i28331# - check that a Value is set | |||
1496 | if ( !rRotate.GetValue() ) | |||
1497 | return; | |||
1498 | ||||
1499 | if (m_rWW8Export.IsInTable()) | |||
1500 | return; | |||
1501 | ||||
1502 | // #i36867 In word the text in a table is rotated via the TC or NS_sprm::TTextFlow::val | |||
1503 | // This means you can only rotate all or none of the text adding NS_sprm::CFELayout::val | |||
1504 | // here corrupts the table, hence !m_rWW8Export.bIsInTable | |||
1505 | ||||
1506 | m_rWW8Export.InsUInt16( NS_sprm::CFELayout::val ); | |||
1507 | m_rWW8Export.pO->push_back( sal_uInt8(0x06) ); //len 6 | |||
1508 | m_rWW8Export.pO->push_back( sal_uInt8(0x01) ); | |||
1509 | ||||
1510 | m_rWW8Export.InsUInt16( rRotate.IsFitToLine() ? 1 : 0 ); | |||
1511 | static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 }; | |||
1512 | m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), aZeroArr, aZeroArr+3); | |||
1513 | } | |||
1514 | ||||
1515 | void WW8AttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark ) | |||
1516 | { | |||
1517 | sal_uInt8 nVal; | |||
1518 | const FontEmphasisMark v = rEmphasisMark.GetEmphasisMark(); | |||
1519 | if (v == FontEmphasisMark::NONE) | |||
1520 | nVal = 0; | |||
1521 | else if (v == (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove)) | |||
1522 | nVal = 2; | |||
1523 | else if (v == (FontEmphasisMark::Circle | FontEmphasisMark::PosAbove)) | |||
1524 | nVal = 3; | |||
1525 | else if (v == (FontEmphasisMark::Dot | FontEmphasisMark::PosBelow)) | |||
1526 | nVal = 4; | |||
1527 | else | |||
1528 | // case 1: | |||
1529 | nVal = 1; | |||
1530 | ||||
1531 | m_rWW8Export.InsUInt16( NS_sprm::CKcd::val ); | |||
1532 | m_rWW8Export.pO->push_back( nVal ); | |||
1533 | } | |||
1534 | ||||
1535 | /** | |||
1536 | * TransBrush converts SW-Brushes to WW. The result is WW8_SHD. | |||
1537 | * Non-standard colours of SW won't be converted now to the mixed values | |||
1538 | * ( 0 .. 95% ) of WW. | |||
1539 | * Also if transparent, e.g. for tables a transparent brush is returned | |||
1540 | * | |||
1541 | * @return real brush ( not transparent ) | |||
1542 | */ | |||
1543 | bool WW8Export::TransBrush(const Color& rCol, WW8_SHD& rShd) | |||
1544 | { | |||
1545 | if( rCol.GetTransparency() ) | |||
1546 | rShd = WW8_SHD(); // all zeros: transparent | |||
1547 | else | |||
1548 | { | |||
1549 | rShd.SetFore( 0); | |||
1550 | rShd.SetBack( msfilter::util::TransColToIco( rCol ) ); | |||
1551 | rShd.SetStyle( 0 ); | |||
1552 | } | |||
1553 | return !rCol.GetTransparency(); | |||
1554 | } | |||
1555 | ||||
1556 | static sal_uInt32 SuitableBGColor(Color nIn) | |||
1557 | { | |||
1558 | if (nIn == COL_AUTO) | |||
1559 | return 0xFF000000; | |||
1560 | return wwUtility::RGBToBGR(nIn); | |||
1561 | } | |||
1562 | ||||
1563 | void WW8AttributeOutput::CharColor( const SvxColorItem& rColor ) | |||
1564 | { | |||
1565 | m_rWW8Export.InsUInt16( NS_sprm::CIco::val ); | |||
1566 | ||||
1567 | sal_uInt8 nColor = msfilter::util::TransColToIco( rColor.GetValue() ); | |||
1568 | m_rWW8Export.pO->push_back( nColor ); | |||
1569 | ||||
1570 | if (nColor) | |||
1571 | { | |||
1572 | m_rWW8Export.InsUInt16( NS_sprm::CCv::val ); | |||
1573 | m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( rColor.GetValue() ) ); | |||
1574 | } | |||
1575 | } | |||
1576 | ||||
1577 | void WW8AttributeOutput::CharBackground( const SvxBrushItem& rBrush ) | |||
1578 | { | |||
1579 | WW8_SHD aSHD; | |||
1580 | ||||
1581 | WW8Export::TransBrush( rBrush.GetColor(), aSHD ); | |||
1582 | // sprmCShd80 | |||
1583 | m_rWW8Export.InsUInt16( NS_sprm::CShd80::val ); | |||
1584 | m_rWW8Export.InsUInt16( aSHD.GetValue() ); | |||
1585 | ||||
1586 | //Quite a few unknowns, some might be transparency or something | |||
1587 | //of that nature... | |||
1588 | m_rWW8Export.InsUInt16( NS_sprm::CShd::val ); | |||
1589 | m_rWW8Export.pO->push_back( 10 ); | |||
1590 | m_rWW8Export.InsUInt32( 0xFF000000 ); | |||
1591 | m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor() ) ); | |||
1592 | m_rWW8Export.InsUInt16( 0x0000); | |||
1593 | } | |||
1594 | ||||
1595 | namespace sw { namespace util { | |||
1596 | ||||
1597 | const SwCharFormat* GetSwCharFormat(const SwFormatINetFormat& rINet, SwDoc& rDoc) | |||
1598 | { | |||
1599 | if (rINet.GetValue().isEmpty()) | |||
1600 | return nullptr; | |||
1601 | ||||
1602 | const sal_uInt16 nId = rINet.GetINetFormatId(); | |||
1603 | const OUString& rStr = rINet.GetINetFormat(); | |||
1604 | if (rStr.isEmpty()) | |||
1605 | { | |||
1606 | OSL_ENSURE( false, "WW8AttributeOutput::TextINetFormat(..) - missing unvisited character format at hyperlink attribute" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "1606" ": "), "%s", "WW8AttributeOutput::TextINetFormat(..) - missing unvisited character format at hyperlink attribute" ); } } while (false); | |||
1607 | } | |||
1608 | ||||
1609 | return IsPoolUserFormat( nId ) | |||
1610 | ? rDoc.FindCharFormatByName( rStr ) | |||
1611 | : rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( nId ); | |||
1612 | } | |||
1613 | ||||
1614 | } } | |||
1615 | ||||
1616 | void WW8AttributeOutput::TextINetFormat( const SwFormatINetFormat& rINet ) | |||
1617 | { | |||
1618 | const SwCharFormat* pFormat = GetSwCharFormat(rINet, m_rWW8Export.m_rDoc); | |||
1619 | if (!pFormat) | |||
1620 | return; | |||
1621 | ||||
1622 | m_rWW8Export.InsUInt16( NS_sprm::CIstd::val ); | |||
1623 | ||||
1624 | m_rWW8Export.InsUInt16( m_rWW8Export.GetId( pFormat ) ); | |||
1625 | } | |||
1626 | ||||
1627 | // #i43956# - add optional parameter <pLinkStr> | |||
1628 | // It's needed to write the hyperlink data for a certain cross-reference | |||
1629 | // - it contains the name of the link target, which is a bookmark. | |||
1630 | // add optional parameter <bIncludeEmptyPicLocation> | |||
1631 | // It is needed to write an empty picture location for page number field separators | |||
1632 | static void InsertSpecialChar( WW8Export& rWrt, sal_uInt8 c, | |||
1633 | OUString const * pLinkStr, | |||
1634 | bool bIncludeEmptyPicLocation = false ) | |||
1635 | { | |||
1636 | ww::bytes aItems; | |||
1637 | rWrt.GetCurrentItems(aItems); | |||
1638 | ||||
1639 | if (c == 0x13) | |||
1640 | rWrt.m_pChpPlc->AppendFkpEntry(rWrt.Strm().Tell()); | |||
1641 | else | |||
1642 | rWrt.m_pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.size(), aItems.data()); | |||
1643 | ||||
1644 | rWrt.WriteChar(c); | |||
1645 | ||||
1646 | // store empty sprmCPicLocation for field separator | |||
1647 | if ( bIncludeEmptyPicLocation && | |||
1648 | ( c == 0x13 || c == 0x14 || c == 0x15 ) ) | |||
1649 | { | |||
1650 | SwWW8Writer::InsUInt16( aItems, NS_sprm::CPicLocation::val ); | |||
1651 | SwWW8Writer::InsUInt32( aItems, 0x00000000 ); | |||
1652 | } | |||
1653 | ||||
1654 | // #i43956# - write hyperlink data and attributes | |||
1655 | if ( c == 0x01 && pLinkStr) | |||
1656 | { | |||
1657 | // write hyperlink data to data stream | |||
1658 | SvStream& rStrm = *rWrt.pDataStrm; | |||
1659 | // position of hyperlink data | |||
1660 | const sal_uInt32 nLinkPosInDataStrm = rStrm.Tell(); | |||
1661 | // write empty header | |||
1662 | const sal_uInt16 nEmptyHdrLen = 0x44; | |||
1663 | sal_uInt8 aEmptyHeader[ nEmptyHdrLen ] = { 0 }; | |||
1664 | aEmptyHeader[ 4 ] = 0x44; | |||
1665 | rStrm.WriteBytes( aEmptyHeader, nEmptyHdrLen ); | |||
1666 | // writer fixed header | |||
1667 | const sal_uInt16 nFixHdrLen = 0x19; | |||
1668 | sal_uInt8 const aFixHeader[ nFixHdrLen ] = | |||
1669 | { | |||
1670 | 0x08, 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, | |||
1671 | 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, | |||
1672 | 0x0B, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, | |||
1673 | 0x00, | |||
1674 | }; | |||
1675 | rStrm.WriteBytes( aFixHeader, nFixHdrLen ); | |||
1676 | // write reference string including length+1 | |||
1677 | sal_uInt32 nStrLen( pLinkStr->getLength() + 1 ); | |||
1678 | SwWW8Writer::WriteLong( rStrm, nStrLen ); | |||
1679 | SwWW8Writer::WriteString16( rStrm, *pLinkStr, false ); | |||
1680 | // write additional two NULL Bytes | |||
1681 | SwWW8Writer::WriteLong( rStrm, 0 ); | |||
1682 | // write length of hyperlink data | |||
1683 | const sal_uInt32 nCurrPos = rStrm.Tell(); | |||
1684 | rStrm.Seek( nLinkPosInDataStrm ); | |||
1685 | rStrm.WriteUInt32(nCurrPos - nLinkPosInDataStrm); | |||
1686 | rStrm.Seek( nCurrPos ); | |||
1687 | ||||
1688 | // write attributes of hyperlink character 0x01 | |||
1689 | SwWW8Writer::InsUInt16( aItems, NS_sprm::CFFldVanish::val ); | |||
1690 | aItems.push_back( sal_uInt8(0x81) ); | |||
1691 | SwWW8Writer::InsUInt16( aItems, NS_sprm::CPicLocation::val ); | |||
1692 | SwWW8Writer::InsUInt32( aItems, nLinkPosInDataStrm ); | |||
1693 | SwWW8Writer::InsUInt16( aItems, NS_sprm::CFData::val ); | |||
1694 | aItems.push_back( sal_uInt8(0x01) ); | |||
1695 | } | |||
1696 | ||||
1697 | //Technically we should probably Remove all attribs | |||
1698 | //here for the 0x13, 0x14, 0x15, but our import | |||
1699 | //is slightly lacking | |||
1700 | //aItems.Remove(0, aItems.Count()); | |||
1701 | // fSpec-Attribute true | |||
1702 | SwWW8Writer::InsUInt16( aItems, NS_sprm::CFSpec::val ); | |||
1703 | aItems.push_back( 1 ); | |||
1704 | ||||
1705 | rWrt.m_pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.size(), aItems.data()); | |||
1706 | } | |||
1707 | ||||
1708 | static OUString lcl_GetExpandedField(const SwField &rField) | |||
1709 | { | |||
1710 | //replace LF 0x0A with VT 0x0B | |||
1711 | return rField.ExpandField(true, nullptr).replace(0x0A, 0x0B); | |||
1712 | } | |||
1713 | ||||
1714 | WW8_WrPlcField* WW8Export::CurrentFieldPlc() const | |||
1715 | { | |||
1716 | WW8_WrPlcField* pFieldP = nullptr; | |||
1717 | switch (m_nTextTyp) | |||
1718 | { | |||
1719 | case TXT_MAINTEXT: | |||
1720 | pFieldP = m_pFieldMain.get(); | |||
1721 | break; | |||
1722 | case TXT_HDFT: | |||
1723 | pFieldP = m_pFieldHdFt.get(); | |||
1724 | break; | |||
1725 | case TXT_FTN: | |||
1726 | pFieldP = m_pFieldFootnote.get(); | |||
1727 | break; | |||
1728 | case TXT_EDN: | |||
1729 | pFieldP = m_pFieldEdn.get(); | |||
1730 | break; | |||
1731 | case TXT_ATN: | |||
1732 | pFieldP = m_pFieldAtn.get(); | |||
1733 | break; | |||
1734 | case TXT_TXTBOX: | |||
1735 | pFieldP = m_pFieldTextBxs.get(); | |||
1736 | break; | |||
1737 | case TXT_HFTXTBOX: | |||
1738 | pFieldP = m_pFieldHFTextBxs.get(); | |||
1739 | break; | |||
1740 | default: | |||
1741 | OSL_ENSURE( false, "what type of SubDoc is that?" )do { if (true && (!(false))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "1741" ": "), "%s", "what type of SubDoc is that?"); } } while (false); | |||
1742 | } | |||
1743 | return pFieldP; | |||
1744 | } | |||
1745 | ||||
1746 | void WW8Export::OutputField( const SwField* pField, ww::eField eFieldType, | |||
1747 | const OUString& rFieldCmd, FieldFlags nMode ) | |||
1748 | { | |||
1749 | OUString sFieldCmd(rFieldCmd); | |||
1750 | switch (eFieldType) | |||
1751 | { | |||
1752 | // map fields that are not supported in WW8 as of Word 2003 | |||
1753 | case ww::eBIBLIOGRAPHY: | |||
1754 | eFieldType = ww::eQUOTE; | |||
1755 | assert(rFieldCmd == FieldString(ww::eBIBLIOGRAPHY))(static_cast <bool> (rFieldCmd == FieldString(ww::eBIBLIOGRAPHY )) ? void (0) : __assert_fail ("rFieldCmd == FieldString(ww::eBIBLIOGRAPHY)" , "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 1755, __extension__ __PRETTY_FUNCTION__)); | |||
1756 | sFieldCmd = FieldString(ww::eQUOTE); | |||
1757 | break; | |||
1758 | case ww::eCITATION: | |||
1759 | eFieldType = ww::eQUOTE; | |||
1760 | assert(rFieldCmd.trim().startsWith("CITATION"))(static_cast <bool> (rFieldCmd.trim().startsWith("CITATION" )) ? void (0) : __assert_fail ("rFieldCmd.trim().startsWith(\"CITATION\")" , "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 1760, __extension__ __PRETTY_FUNCTION__)); | |||
1761 | sFieldCmd = rFieldCmd.replaceFirst(FieldString(ww::eCITATION), | |||
1762 | FieldString(ww::eQUOTE)); | |||
1763 | break; | |||
1764 | default: | |||
1765 | break; | |||
1766 | } | |||
1767 | ||||
1768 | assert(eFieldType <= 0x5F)(static_cast <bool> (eFieldType <= 0x5F) ? void (0) : __assert_fail ("eFieldType <= 0x5F", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 1768, __extension__ __PRETTY_FUNCTION__)); // 95 is the highest documented one | |||
1769 | ||||
1770 | WW8_WrPlcField* pFieldP = CurrentFieldPlc(); | |||
1771 | ||||
1772 | const bool bIncludeEmptyPicLocation = ( eFieldType == ww::ePAGE ); | |||
1773 | if (FieldFlags::Start & nMode) | |||
1774 | { | |||
1775 | sal_uInt8 aField13[2] = { 0x13, 0x00 }; // will change | |||
1776 | //#i3958#, Needed to make this field work correctly in Word 2000 | |||
1777 | if (eFieldType == ww::eSHAPE) | |||
1778 | aField13[0] |= 0x80; | |||
1779 | aField13[1] = static_cast< sal_uInt8 >(eFieldType); // add type | |||
1780 | pFieldP->Append( Fc2Cp( Strm().Tell() ), aField13 ); | |||
1781 | InsertSpecialChar( *this, 0x13, nullptr, bIncludeEmptyPicLocation ); | |||
1782 | } | |||
1783 | if (FieldFlags::CmdStart & nMode) | |||
1784 | { | |||
1785 | SwWW8Writer::WriteString16(Strm(), sFieldCmd, false); | |||
1786 | // #i43956# - write hyperlink character including | |||
1787 | // attributes and corresponding binary data for certain reference fields. | |||
1788 | bool bHandleBookmark = false; | |||
1789 | ||||
1790 | if (pField) | |||
1791 | { | |||
1792 | if (pField->GetTyp()->Which() == SwFieldIds::GetRef && | |||
1793 | ( eFieldType == ww::ePAGEREF || eFieldType == ww::eREF || | |||
1794 | eFieldType == ww::eNOTEREF || eFieldType == ww::eFOOTREF )) | |||
1795 | bHandleBookmark = true; | |||
1796 | } | |||
1797 | ||||
1798 | if ( bHandleBookmark ) | |||
1799 | { | |||
1800 | // retrieve reference destination - the name of the bookmark | |||
1801 | OUString aLinkStr; | |||
1802 | const sal_uInt16 nSubType = pField->GetSubType(); | |||
1803 | const SwGetRefField& rRField = *static_cast<const SwGetRefField*>(pField); | |||
1804 | if ( nSubType == REF_SETREFATTR || | |||
1805 | nSubType == REF_BOOKMARK ) | |||
1806 | { | |||
1807 | const OUString& aRefName(rRField.GetSetRefName()); | |||
1808 | aLinkStr = GetBookmarkName( nSubType, &aRefName, 0 ); | |||
1809 | } | |||
1810 | else if ( nSubType == REF_FOOTNOTE || | |||
1811 | nSubType == REF_ENDNOTE ) | |||
1812 | { | |||
1813 | aLinkStr = GetBookmarkName( nSubType, nullptr, rRField.GetSeqNo() ); | |||
1814 | } | |||
1815 | else if ( nSubType == REF_SEQUENCEFLD ) | |||
1816 | { | |||
1817 | aLinkStr = pField->GetPar2(); | |||
1818 | } | |||
1819 | // insert hyperlink character including attributes and data. | |||
1820 | InsertSpecialChar( *this, 0x01, &aLinkStr ); | |||
1821 | } | |||
1822 | } | |||
1823 | if (FieldFlags::CmdEnd & nMode) | |||
1824 | { | |||
1825 | static const sal_uInt8 aField14[2] = { 0x14, 0xff }; | |||
1826 | pFieldP->Append( Fc2Cp( Strm().Tell() ), aField14 ); | |||
1827 | pFieldP->ResultAdded(); | |||
1828 | InsertSpecialChar( *this, 0x14, nullptr, bIncludeEmptyPicLocation ); | |||
1829 | } | |||
1830 | if (FieldFlags::End & nMode) | |||
1831 | { | |||
1832 | OUString sOut; | |||
1833 | if( pField ) | |||
1834 | sOut = lcl_GetExpandedField(*pField); | |||
1835 | else | |||
1836 | sOut = sFieldCmd; | |||
1837 | if( !sOut.isEmpty() ) | |||
1838 | { | |||
1839 | SwWW8Writer::WriteString16(Strm(), sOut, false); | |||
1840 | ||||
1841 | if (pField) | |||
1842 | { | |||
1843 | if (pField->GetTyp()->Which() == SwFieldIds::Input && | |||
1844 | eFieldType == ww::eFORMTEXT) | |||
1845 | { | |||
1846 | sal_uInt8 aArr[12]; | |||
1847 | sal_uInt8 *pArr = aArr; | |||
1848 | ||||
1849 | Set_UInt16( pArr, NS_sprm::CPicLocation::val ); | |||
1850 | Set_UInt32( pArr, 0x0 ); | |||
1851 | ||||
1852 | Set_UInt16( pArr, NS_sprm::CFSpec::val ); | |||
1853 | Set_UInt8( pArr, 1 ); | |||
1854 | ||||
1855 | Set_UInt16( pArr, NS_sprm::CFNoProof::val ); | |||
1856 | Set_UInt8( pArr, 1 ); | |||
1857 | ||||
1858 | m_pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr ); | |||
1859 | } | |||
1860 | } | |||
1861 | } | |||
1862 | } | |||
1863 | if (!(FieldFlags::Close & nMode)) | |||
1864 | return; | |||
1865 | ||||
1866 | sal_uInt8 aField15[2] = { 0x15, 0x80 }; | |||
1867 | ||||
1868 | if (pField) | |||
1869 | { | |||
1870 | if (pField->GetTyp()->Which() == SwFieldIds::Input && | |||
1871 | eFieldType == ww::eFORMTEXT) | |||
1872 | { | |||
1873 | sal_uInt16 nSubType = pField->GetSubType(); | |||
1874 | ||||
1875 | if (nSubType == REF_SEQUENCEFLD) | |||
1876 | aField15[0] |= (0x4 << 5); | |||
1877 | } | |||
1878 | } | |||
1879 | ||||
1880 | pFieldP->Append( Fc2Cp( Strm().Tell() ), aField15 ); | |||
1881 | InsertSpecialChar( *this, 0x15, nullptr, bIncludeEmptyPicLocation ); | |||
1882 | } | |||
1883 | ||||
1884 | void WW8Export::StartCommentOutput(const OUString& rName) | |||
1885 | { | |||
1886 | const OUString sStr{ FieldString(ww::eQUOTE) + "[" + rName + "] " }; | |||
1887 | OutputField(nullptr, ww::eQUOTE, sStr, FieldFlags::Start | FieldFlags::CmdStart); | |||
1888 | } | |||
1889 | ||||
1890 | void WW8Export::EndCommentOutput(const OUString& rName) | |||
1891 | { | |||
1892 | const OUString sStr{ " [" + rName + "] " }; | |||
1893 | OutputField(nullptr, ww::eQUOTE, sStr, FieldFlags::CmdEnd | FieldFlags::End | | |||
1894 | FieldFlags::Close); | |||
1895 | } | |||
1896 | ||||
1897 | sal_uInt16 MSWordExportBase::GetId( const SwTOXType& rTOXType ) | |||
1898 | { | |||
1899 | std::vector<const SwTOXType*>::iterator it | |||
1900 | = std::find( m_aTOXArr.begin(), m_aTOXArr.end(), &rTOXType ); | |||
1901 | if ( it != m_aTOXArr.end() ) | |||
1902 | { | |||
1903 | return it - m_aTOXArr.begin(); | |||
1904 | } | |||
1905 | m_aTOXArr.push_back( &rTOXType ); | |||
1906 | return m_aTOXArr.size() - 1; | |||
1907 | } | |||
1908 | ||||
1909 | // return values: 1 - no PageNum, | |||
1910 | // 2 - TabStop before PageNum, | |||
1911 | // 3 - Text before PageNum - rText hold the text | |||
1912 | // 4 - no Text and no TabStop before PageNum | |||
1913 | static int lcl_CheckForm( const SwForm& rForm, sal_uInt8 nLvl, OUString& rText ) | |||
1914 | { | |||
1915 | int nRet = 4; | |||
1916 | rText.clear(); | |||
1917 | ||||
1918 | // #i21237# | |||
1919 | SwFormTokens aPattern = rForm.GetPattern(nLvl); | |||
1920 | SwFormTokens::iterator aIt = aPattern.begin(); | |||
1921 | FormTokenType eTType; | |||
1922 | ||||
1923 | // #i61362# | |||
1924 | if (! aPattern.empty()) | |||
1925 | { | |||
1926 | bool bPgNumFnd = false; | |||
1927 | ||||
1928 | // #i21237# | |||
1929 | while( ++aIt != aPattern.end() && !bPgNumFnd ) | |||
1930 | { | |||
1931 | eTType = aIt->eTokenType; | |||
1932 | ||||
1933 | switch( eTType ) | |||
1934 | { | |||
1935 | case TOKEN_PAGE_NUMS: | |||
1936 | bPgNumFnd = true; | |||
1937 | break; | |||
1938 | ||||
1939 | case TOKEN_TAB_STOP: | |||
1940 | nRet = 2; | |||
1941 | break; | |||
1942 | case TOKEN_TEXT: | |||
1943 | { | |||
1944 | nRet = 3; | |||
1945 | sal_Int32 nCount = std::min<sal_Int32>(5, aIt->sText.getLength()); | |||
1946 | rText = aIt->sText.copy(0, nCount); // #i21237# | |||
1947 | break; | |||
1948 | } | |||
1949 | case TOKEN_LINK_START: | |||
1950 | case TOKEN_LINK_END: | |||
1951 | break; | |||
1952 | ||||
1953 | default: | |||
1954 | nRet = 4; | |||
1955 | break; | |||
1956 | } | |||
1957 | } | |||
1958 | ||||
1959 | if( !bPgNumFnd ) | |||
1960 | nRet = 1; | |||
1961 | } | |||
1962 | ||||
1963 | return nRet; | |||
1964 | } | |||
1965 | ||||
1966 | static bool lcl_IsHyperlinked(const SwForm& rForm, sal_uInt16 nTOXLvl) | |||
1967 | { | |||
1968 | bool bRes = false; | |||
1969 | for (sal_uInt16 nI = 1; nI < nTOXLvl; ++nI) | |||
1970 | { | |||
1971 | // #i21237# | |||
1972 | SwFormTokens aPattern = rForm.GetPattern(nI); | |||
1973 | ||||
1974 | if ( !aPattern.empty() ) | |||
1975 | { | |||
1976 | SwFormTokens::iterator aIt = aPattern.begin(); | |||
1977 | ||||
1978 | FormTokenType eTType; | |||
1979 | ||||
1980 | // #i21237# | |||
1981 | while ( ++aIt != aPattern.end() ) | |||
1982 | { | |||
1983 | eTType = aIt->eTokenType; | |||
1984 | switch (eTType) | |||
1985 | { | |||
1986 | case TOKEN_LINK_START: | |||
1987 | case TOKEN_LINK_END: | |||
1988 | bRes = true; | |||
1989 | break; | |||
1990 | default: | |||
1991 | ; | |||
1992 | } | |||
1993 | } | |||
1994 | } | |||
1995 | } | |||
1996 | return bRes; | |||
1997 | } | |||
1998 | ||||
1999 | void AttributeOutputBase::GenerateBookmarksForSequenceField(const SwTextNode& rNode, SwWW8AttrIter& rAttrIter) | |||
2000 | { | |||
2001 | if(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF) // Not implemented for RTF | |||
2002 | return; | |||
2003 | ||||
2004 | const SwpHints* pTextAttrs = rNode.GetpSwpHints(); | |||
2005 | if (!pTextAttrs) | |||
2006 | return; | |||
2007 | ||||
2008 | for( size_t i = 0; i < pTextAttrs->Count(); ++i ) | |||
2009 | { | |||
2010 | const SwTextAttr* pHt = pTextAttrs->Get(i); | |||
2011 | if (pHt->GetAttr().Which() == RES_TXTATR_FIELD) | |||
2012 | { | |||
2013 | const SwFormatField& rField = static_cast<const SwFormatField&>(pHt->GetAttr()); | |||
2014 | const SwField* pField = rField.GetField(); | |||
2015 | // Need to have bookmarks only for sequence fields | |||
2016 | if (pField && pField->GetTyp()->Which() == SwFieldIds::SetExp && pField->GetSubType() == nsSwGetSetExpType::GSE_SEQ) | |||
2017 | { | |||
2018 | const sal_uInt16 nSeqFieldNumber = static_cast<const SwSetExpField*>(pField)->GetSeqNumber(); | |||
2019 | const OUString sObjectName = static_cast<const SwSetExpFieldType*>(pField->GetTyp())->GetName(); | |||
2020 | const SwFieldTypes* pFieldTypes = GetExport().m_rDoc.getIDocumentFieldsAccess().GetFieldTypes(); | |||
2021 | bool bHaveFullBkm = false; | |||
2022 | bool bHaveLabelAndNumberBkm = false; | |||
2023 | bool bHaveCaptionOnlyBkm = false; | |||
2024 | bool bHaveNumberOnlyBkm = false; | |||
2025 | bool bRunSplittedAtSep = false; | |||
2026 | for( auto const & pFieldType : *pFieldTypes ) | |||
2027 | { | |||
2028 | if( SwFieldIds::GetRef == pFieldType->Which() ) | |||
2029 | { | |||
2030 | SwIterator<SwFormatField,SwFieldType> aIter( *pFieldType ); | |||
2031 | for( SwFormatField* pFormatField = aIter.First(); pFormatField; pFormatField = aIter.Next() ) | |||
2032 | { | |||
2033 | SwGetRefField* pRefField = static_cast<SwGetRefField*>(pFormatField->GetField()); | |||
2034 | // If we have a reference to the current sequence field | |||
2035 | if(pRefField->GetSeqNo() == nSeqFieldNumber && pRefField->GetSetRefName() == sObjectName) | |||
2036 | { | |||
2037 | // Need to create a separate run for separator character | |||
2038 | SwWW8AttrIter aLocalAttrIter( GetExport(), rNode ); // We need a local iterator having the right number of runs | |||
2039 | const OUString& aText = rNode.GetText(); | |||
2040 | const sal_Int32 nCategoryStart = aText.indexOf(pRefField->GetSetRefName()); | |||
2041 | const sal_Int32 nPosBeforeSeparator = std::max(nCategoryStart, pHt->GetStart()); | |||
2042 | bool bCategoryFirst = nCategoryStart < pHt->GetStart(); | |||
2043 | sal_Int32 nSeparatorPos = 0; | |||
2044 | if (bCategoryFirst) | |||
2045 | { | |||
2046 | nSeparatorPos = aLocalAttrIter.WhereNext(); | |||
2047 | while (nSeparatorPos <= nPosBeforeSeparator) | |||
2048 | { | |||
2049 | aLocalAttrIter.NextPos(); | |||
2050 | nSeparatorPos = aLocalAttrIter.WhereNext(); | |||
2051 | } | |||
2052 | } | |||
2053 | else | |||
2054 | { | |||
2055 | nSeparatorPos = nCategoryStart + pRefField->GetSetRefName().getLength(); | |||
2056 | } | |||
2057 | sal_Int32 nRefTextPos = 0; | |||
2058 | if(nSeparatorPos < aText.getLength()) | |||
2059 | { | |||
2060 | nRefTextPos = SwGetExpField::GetReferenceTextPos(pHt->GetFormatField(), GetExport().m_rDoc, nSeparatorPos); | |||
2061 | if(nRefTextPos != nSeparatorPos) | |||
2062 | { | |||
2063 | if(!bRunSplittedAtSep) | |||
2064 | { | |||
2065 | if(!bCategoryFirst) | |||
2066 | rAttrIter.SplitRun(nSeparatorPos); | |||
2067 | rAttrIter.SplitRun(nRefTextPos); | |||
2068 | bRunSplittedAtSep = true; | |||
2069 | } | |||
2070 | if(!bCategoryFirst) | |||
2071 | aLocalAttrIter.SplitRun(nSeparatorPos); | |||
2072 | aLocalAttrIter.SplitRun(nRefTextPos); | |||
2073 | } | |||
2074 | else if (bCategoryFirst) | |||
2075 | { | |||
2076 | if(!bRunSplittedAtSep) | |||
2077 | { | |||
2078 | rAttrIter.SplitRun(nSeparatorPos); | |||
2079 | bRunSplittedAtSep = true; | |||
2080 | } | |||
2081 | aLocalAttrIter.SplitRun(nSeparatorPos); | |||
2082 | } | |||
2083 | } | |||
2084 | // Generate bookmarks on the right position | |||
2085 | OUString sName("Ref_" + pRefField->GetSetRefName() + OUString::number(pRefField->GetSeqNo())); | |||
2086 | switch (pRefField->GetFormat()) | |||
2087 | { | |||
2088 | case REF_PAGE: | |||
2089 | case REF_PAGE_PGDESC: | |||
2090 | case REF_CONTENT: | |||
2091 | case REF_UPDOWN: | |||
2092 | if(!bHaveFullBkm) | |||
2093 | { | |||
2094 | sal_Int32 nLastAttrStart = 0; | |||
2095 | sal_Int32 nActAttr = aLocalAttrIter.WhereNext(); | |||
2096 | while (nActAttr < rNode.GetText().getLength()) | |||
2097 | { | |||
2098 | nLastAttrStart = nActAttr; | |||
2099 | aLocalAttrIter.NextPos(); | |||
2100 | nActAttr = aLocalAttrIter.WhereNext(); | |||
2101 | } | |||
2102 | WriteBookmarkInActParagraph( sName + "_full", std::min(nCategoryStart, pHt->GetStart()), nLastAttrStart ); | |||
2103 | bHaveFullBkm = true; | |||
2104 | } | |||
2105 | break; | |||
2106 | case REF_ONLYNUMBER: | |||
2107 | { | |||
2108 | if(!bHaveLabelAndNumberBkm) | |||
2109 | { | |||
2110 | sName += "_label_and_number"; | |||
2111 | if(bCategoryFirst) | |||
2112 | WriteBookmarkInActParagraph( sName, std::min(nCategoryStart, pHt->GetStart()), std::max(nCategoryStart, pHt->GetStart()) ); | |||
2113 | else | |||
2114 | { | |||
2115 | // Find the last run which contains category text | |||
2116 | SwWW8AttrIter aLocalAttrIter2( GetExport(), rNode ); | |||
2117 | sal_Int32 nCatLastRun = 0; | |||
2118 | sal_Int32 nNextAttr = aLocalAttrIter2.WhereNext(); | |||
2119 | while (nNextAttr < nSeparatorPos) | |||
2120 | { | |||
2121 | nCatLastRun = nNextAttr; | |||
2122 | aLocalAttrIter2.NextPos(); | |||
2123 | nNextAttr = aLocalAttrIter2.WhereNext(); | |||
2124 | } | |||
2125 | WriteBookmarkInActParagraph( sName, pHt->GetStart(), nCatLastRun ); | |||
2126 | } | |||
2127 | bHaveLabelAndNumberBkm = true; | |||
2128 | } | |||
2129 | break; | |||
2130 | } | |||
2131 | case REF_ONLYCAPTION: | |||
2132 | { | |||
2133 | if(!bHaveCaptionOnlyBkm) | |||
2134 | { | |||
2135 | // Find last run | |||
2136 | sal_Int32 nLastAttrStart = 0; | |||
2137 | sal_Int32 nActAttr = aLocalAttrIter.WhereNext(); | |||
2138 | while (nActAttr < rNode.GetText().getLength()) | |||
2139 | { | |||
2140 | nLastAttrStart = nActAttr; | |||
2141 | aLocalAttrIter.NextPos(); | |||
2142 | nActAttr = aLocalAttrIter.WhereNext(); | |||
2143 | } | |||
2144 | WriteBookmarkInActParagraph( sName + "_caption_only", nRefTextPos, nLastAttrStart ); | |||
2145 | bHaveCaptionOnlyBkm = true; | |||
2146 | } | |||
2147 | break; | |||
2148 | } | |||
2149 | case REF_ONLYSEQNO: | |||
2150 | { | |||
2151 | if(!bHaveNumberOnlyBkm) | |||
2152 | { | |||
2153 | WriteBookmarkInActParagraph( sName + "_number_only", pHt->GetStart(), pHt->GetStart() ); | |||
2154 | bHaveNumberOnlyBkm = true; | |||
2155 | } | |||
2156 | break; | |||
2157 | } | |||
2158 | } | |||
2159 | } | |||
2160 | } | |||
2161 | } | |||
2162 | } | |||
2163 | return; | |||
2164 | } | |||
2165 | } | |||
2166 | } | |||
2167 | } | |||
2168 | ||||
2169 | void AttributeOutputBase::StartTOX( const SwSection& rSect ) | |||
2170 | { | |||
2171 | if ( const SwTOXBase* pTOX = rSect.GetTOXBase() ) | |||
2172 | { | |||
2173 | static const char sEntryEnd[] = "\" "; | |||
2174 | ||||
2175 | ww::eField eCode = ww::eTOC; | |||
2176 | OUString sStr = pTOX ->GetMSTOCExpression(); | |||
2177 | if ( sStr.isEmpty() ) | |||
2178 | { | |||
2179 | switch (pTOX->GetType()) | |||
2180 | { | |||
2181 | case TOX_INDEX: | |||
2182 | eCode = ww::eINDEX; | |||
2183 | sStr = FieldString(eCode); | |||
2184 | ||||
2185 | { | |||
2186 | const SwFormatCol& rCol = rSect.GetFormat()->GetFormatAttr( RES_COL ); | |||
2187 | const SwColumns& rColumns = rCol.GetColumns(); | |||
2188 | sal_Int32 nCol = rColumns.size(); | |||
2189 | ||||
2190 | if ( 0 < nCol ) | |||
2191 | { | |||
2192 | // Add a continuous section break | |||
2193 | if( GetExport().AddSectionBreaksForTOX() ) | |||
2194 | { | |||
2195 | SwSection *pParent = rSect.GetParent(); | |||
2196 | WW8_SepInfo rInfo(&GetExport().m_rDoc.GetPageDesc(0), | |||
2197 | pParent ? pParent->GetFormat() : nullptr, 0/*nRstLnNum*/); | |||
2198 | GetExport( ).AttrOutput().SectionBreak( msword::PageBreak, false, &rInfo ); | |||
2199 | } | |||
2200 | ||||
2201 | sStr += "\\c \"" + OUString::number( nCol ) + "\""; | |||
2202 | } | |||
2203 | } | |||
2204 | ||||
2205 | if (pTOX->GetTOXForm().IsCommaSeparated()) | |||
2206 | sStr += "\\r "; | |||
2207 | ||||
2208 | if (SwTOIOptions::AlphaDelimiter & pTOX->GetOptions()) | |||
2209 | sStr += "\\h \"A\" "; | |||
2210 | ||||
2211 | if(SwTOXElement::IndexEntryType & pTOX->GetCreateType()) | |||
2212 | { | |||
2213 | sStr += "\\f "; | |||
2214 | const OUString& sName = pTOX->GetEntryTypeName(); | |||
2215 | if(!sName.isEmpty()) | |||
2216 | { | |||
2217 | sStr += sName + sEntryEnd; | |||
2218 | } | |||
2219 | } | |||
2220 | ||||
2221 | if (!pTOX->GetTOXForm().IsCommaSeparated()) | |||
2222 | { | |||
2223 | // In case of Run-in style no separators are added. | |||
2224 | OUString aFillText; | |||
2225 | for (sal_uInt8 n = 1; n <= 3; ++n) | |||
2226 | { | |||
2227 | OUString aText; | |||
2228 | int nRet = ::lcl_CheckForm(pTOX->GetTOXForm(), n, aText); | |||
2229 | ||||
2230 | if( 3 == nRet ) | |||
2231 | aFillText = aText; | |||
2232 | else if ((4 == nRet) || (2 == nRet)) | |||
2233 | aFillText = "\t"; | |||
2234 | else | |||
2235 | aFillText.clear(); | |||
2236 | } | |||
2237 | sStr += "\\e \"" + aFillText + sEntryEnd; | |||
2238 | } | |||
2239 | break; | |||
2240 | ||||
2241 | case TOX_ILLUSTRATIONS: | |||
2242 | case TOX_OBJECTS: | |||
2243 | case TOX_TABLES: | |||
2244 | if (!pTOX->IsFromObjectNames()) | |||
2245 | { | |||
2246 | sStr = FieldString(eCode) + "\\c "; | |||
2247 | const OUString& seqName = pTOX->GetSequenceName(); | |||
2248 | if(!seqName.isEmpty()) | |||
2249 | { | |||
2250 | sStr += "\"" + seqName + sEntryEnd; | |||
2251 | } | |||
2252 | OUString aText; | |||
2253 | int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), 1, aText ); | |||
2254 | if (1 == nRet) | |||
2255 | sStr += "\\n "; | |||
2256 | else if( 3 == nRet || 4 == nRet ) | |||
2257 | { | |||
2258 | sStr += "\\p \"" + aText + sEntryEnd; | |||
2259 | } | |||
2260 | } | |||
2261 | break; | |||
2262 | ||||
2263 | case TOX_AUTHORITIES: | |||
2264 | eCode = ww::eBIBLIOGRAPHY; | |||
2265 | sStr = FieldString(eCode); | |||
2266 | break; | |||
2267 | // case TOX_USER: | |||
2268 | // case TOX_CONTENT: | |||
2269 | default: | |||
2270 | { | |||
2271 | sStr = FieldString(eCode); | |||
2272 | ||||
2273 | OUString sTOption; | |||
2274 | sal_uInt16 n, nTOXLvl = pTOX->GetLevel(); | |||
2275 | if( !nTOXLvl ) | |||
2276 | ++nTOXLvl; | |||
2277 | ||||
2278 | if(SwTOXElement::TableLeader & pTOX->GetCreateType()) | |||
2279 | { | |||
2280 | sStr +="\\z " ; | |||
2281 | GetExport( ).m_bHideTabLeaderAndPageNumbers = true ; | |||
2282 | } | |||
2283 | if(SwTOXElement::TableInToc & pTOX->GetCreateType()) | |||
2284 | { | |||
2285 | sStr +="\\w " ; | |||
2286 | GetExport( ).m_bTabInTOC = true ; | |||
2287 | } | |||
2288 | if(SwTOXElement::Newline & pTOX->GetCreateType()) | |||
2289 | { | |||
2290 | sStr +="\\x " ; | |||
2291 | } | |||
2292 | if( SwTOXElement::Mark & pTOX->GetCreateType() ) | |||
2293 | { | |||
2294 | sStr += "\\f "; | |||
2295 | ||||
2296 | if( TOX_USER == pTOX->GetType() ) | |||
2297 | { | |||
2298 | sStr += "\"" | |||
2299 | + OUStringChar(static_cast<char>( 'A' + GetExport( ).GetId( *pTOX->GetTOXType() ) )) | |||
2300 | + sEntryEnd; | |||
2301 | } | |||
2302 | } | |||
2303 | if(SwTOXElement::Bookmark & pTOX->GetCreateType()) | |||
2304 | { | |||
2305 | sStr += "\\b \"" + pTOX->GetBookmarkName() + sEntryEnd; | |||
2306 | } | |||
2307 | ||||
2308 | if( SwTOXElement::OutlineLevel & pTOX->GetCreateType() ) | |||
2309 | { | |||
2310 | // Take the TOC value of the max level to evaluate to as | |||
2311 | // the starting point for the \o flag, but reduce it to the | |||
2312 | // value of the highest outline level filled by a *standard* | |||
2313 | // Heading 1 - 9 style because \o "Builds a table of | |||
2314 | // contents from paragraphs formatted with built-in heading | |||
2315 | // styles". And afterward fill in any outline styles left | |||
2316 | // uncovered by that range to the \t flag | |||
2317 | ||||
2318 | // i.e. for | |||
2319 | // Heading 1 | |||
2320 | // Heading 2 | |||
2321 | // custom-style | |||
2322 | // Heading 4 | |||
2323 | // output | |||
2324 | // \o 1-2 \tcustom-style,3,Heading 3,4 | |||
2325 | ||||
2326 | // Search over all the outline styles used and figure out | |||
2327 | // what is the minimum outline level (if any) filled by a | |||
2328 | // non-standard style for that level, i.e. ignore headline | |||
2329 | // styles 1-9 and find the lowest valid outline level | |||
2330 | sal_uInt8 nPosOfLowestNonStandardLvl = MAXLEVEL; | |||
2331 | const SwTextFormatColls& rColls = *GetExport().m_rDoc.GetTextFormatColls(); | |||
2332 | for( n = rColls.size(); n; ) | |||
2333 | { | |||
2334 | const SwTextFormatColl* pColl = rColls[ --n ]; | |||
2335 | sal_uInt16 nPoolId = pColl->GetPoolFormatId(); | |||
2336 | if ( | |||
2337 | //Is a Non-Standard Outline Style | |||
2338 | (RES_POOLCOLL_HEADLINE1 > nPoolId || RES_POOLCOLL_HEADLINE9 < nPoolId) && | |||
2339 | //Has a valid outline level | |||
2340 | (pColl->IsAssignedToListLevelOfOutlineStyle()) && | |||
2341 | // Is less than the lowest known non-standard level | |||
2342 | (pColl->GetAssignedOutlineStyleLevel() < nPosOfLowestNonStandardLvl) | |||
2343 | ) | |||
2344 | { | |||
2345 | nPosOfLowestNonStandardLvl = ::sal::static_int_cast<sal_uInt8>(pColl->GetAssignedOutlineStyleLevel()); | |||
2346 | } | |||
2347 | } | |||
2348 | ||||
2349 | sal_uInt8 nMaxMSAutoEvaluate = nPosOfLowestNonStandardLvl < nTOXLvl ? nPosOfLowestNonStandardLvl : static_cast<sal_uInt8>(nTOXLvl); | |||
2350 | ||||
2351 | //output \o 1-X where X is the highest normal outline style to be included in the toc | |||
2352 | if ( nMaxMSAutoEvaluate ) | |||
2353 | { | |||
2354 | if (nMaxMSAutoEvaluate > WW8ListManager::nMaxLevel) | |||
2355 | nMaxMSAutoEvaluate = WW8ListManager::nMaxLevel; | |||
2356 | ||||
2357 | sStr += "\\o \"1-" + OUString::number(nMaxMSAutoEvaluate) + sEntryEnd; | |||
2358 | } | |||
2359 | ||||
2360 | //collect up any other styles in the writer TOC which will | |||
2361 | //not already appear in the MS TOC and place then into the | |||
2362 | //\t option | |||
2363 | if( nMaxMSAutoEvaluate < nTOXLvl ) | |||
2364 | { | |||
2365 | // collect this templates into the \t option | |||
2366 | for( n = rColls.size(); n;) | |||
2367 | { | |||
2368 | const SwTextFormatColl* pColl = rColls[ --n ]; | |||
2369 | if (!pColl->IsAssignedToListLevelOfOutlineStyle()) | |||
2370 | continue; | |||
2371 | sal_uInt8 nTestLvl = ::sal::static_int_cast<sal_uInt8>(pColl->GetAssignedOutlineStyleLevel()); | |||
2372 | if (nTestLvl < nTOXLvl && nTestLvl >= nMaxMSAutoEvaluate) | |||
2373 | { | |||
2374 | if (!sTOption.isEmpty()) | |||
2375 | sTOption += ","; | |||
2376 | sTOption += pColl->GetName() + "," + OUString::number( nTestLvl + 1 ); | |||
2377 | } | |||
2378 | } | |||
2379 | } | |||
2380 | } | |||
2381 | ||||
2382 | if( SwTOXElement::ParagraphOutlineLevel & pTOX->GetCreateType() ) | |||
2383 | { | |||
2384 | sStr +="\\u " ; | |||
2385 | } | |||
2386 | ||||
2387 | if( SwTOXElement::Template & pTOX->GetCreateType() ) | |||
2388 | { | |||
2389 | // #i99641# - Consider additional styles regardless of TOX-outlinelevel | |||
2390 | for( n = 0; n < MAXLEVEL; ++n ) | |||
2391 | { | |||
2392 | const OUString& rStyles = pTOX->GetStyleNames( n ); | |||
2393 | if( !rStyles.isEmpty() ) | |||
2394 | { | |||
2395 | sal_Int32 nPos = 0; | |||
2396 | const OUString sLvl{ "," + OUString::number( n + 1 ) }; | |||
2397 | do { | |||
2398 | const OUString sStyle( rStyles.getToken( 0, TOX_STYLE_DELIMITERu'\x0001', nPos )); | |||
2399 | if( !sStyle.isEmpty() ) | |||
2400 | { | |||
2401 | SwTextFormatColl* pColl = GetExport().m_rDoc.FindTextFormatCollByName(sStyle); | |||
2402 | if (pColl) | |||
2403 | { | |||
2404 | if (!pColl->IsAssignedToListLevelOfOutlineStyle() || pColl->GetAssignedOutlineStyleLevel() < nTOXLvl) | |||
2405 | { | |||
2406 | if( !sTOption.isEmpty() ) | |||
2407 | sTOption += ","; | |||
2408 | sTOption += sStyle + sLvl; | |||
2409 | } | |||
2410 | } | |||
2411 | } | |||
2412 | } while( -1 != nPos ); | |||
2413 | } | |||
2414 | } | |||
2415 | } | |||
2416 | ||||
2417 | // No 'else' branch; why the below snippet is a block I have no idea. | |||
2418 | { | |||
2419 | OUString aFillText; | |||
2420 | sal_uInt8 nNoPgStt = MAXLEVEL, nNoPgEnd = MAXLEVEL; | |||
2421 | bool bFirstFillText = true, bOnlyText = true; | |||
2422 | for( n = 0; n < nTOXLvl; ++n ) | |||
2423 | { | |||
2424 | OUString aText; | |||
2425 | int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), | |||
2426 | static_cast< sal_uInt8 >(n+1), aText ); | |||
2427 | if( 1 == nRet ) | |||
2428 | { | |||
2429 | bOnlyText = false; | |||
2430 | if( MAXLEVEL == nNoPgStt ) | |||
2431 | nNoPgStt = static_cast< sal_uInt8 >(n+1); | |||
2432 | } | |||
2433 | else | |||
2434 | { | |||
2435 | if( MAXLEVEL != nNoPgStt && | |||
2436 | MAXLEVEL == nNoPgEnd ) | |||
2437 | nNoPgEnd = sal_uInt8(n); | |||
2438 | ||||
2439 | bOnlyText = bOnlyText && 3 == nRet; | |||
2440 | if( 3 == nRet || 4 == nRet ) | |||
2441 | { | |||
2442 | if( bFirstFillText ) | |||
2443 | aFillText = aText; | |||
2444 | else if( aFillText != aText ) | |||
2445 | aFillText.clear(); | |||
2446 | bFirstFillText = false; | |||
2447 | } | |||
2448 | } | |||
2449 | } | |||
2450 | if( MAXLEVEL != nNoPgStt ) | |||
2451 | { | |||
2452 | if (WW8ListManager::nMaxLevel < nNoPgEnd) | |||
2453 | nNoPgEnd = WW8ListManager::nMaxLevel; | |||
2454 | sStr += "\\n " | |||
2455 | + OUString::number( nNoPgStt ) | |||
2456 | + "-" | |||
2457 | + OUString::number( nNoPgEnd ) | |||
2458 | + " "; | |||
2459 | } | |||
2460 | if( bOnlyText ) | |||
2461 | { | |||
2462 | sStr += "\\p \"" + aFillText + sEntryEnd; | |||
2463 | } | |||
2464 | } | |||
2465 | ||||
2466 | if( !sTOption.isEmpty() ) | |||
2467 | { | |||
2468 | sStr += "\\t \"" + sTOption + sEntryEnd; | |||
2469 | } | |||
2470 | ||||
2471 | if (lcl_IsHyperlinked(pTOX->GetTOXForm(), nTOXLvl)) | |||
2472 | sStr += "\\h"; | |||
2473 | break; | |||
2474 | } | |||
2475 | } | |||
2476 | } | |||
2477 | ||||
2478 | if (!sStr.isEmpty()) | |||
2479 | { | |||
2480 | GetExport( ).m_bInWriteTOX = true; | |||
2481 | if (GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF) | |||
2482 | { // tdf#129574: required for RTF; doesn't work with DOCX | |||
2483 | StartRun(nullptr, -42, true); | |||
2484 | } | |||
2485 | GetExport( ).OutputField( nullptr, eCode, sStr, FieldFlags::Start | FieldFlags::CmdStart | | |||
2486 | FieldFlags::CmdEnd ); | |||
2487 | if (GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF) | |||
2488 | { | |||
2489 | EndRun(nullptr, -42, true); | |||
2490 | } | |||
2491 | } | |||
2492 | } | |||
2493 | ||||
2494 | GetExport( ).m_bStartTOX = false; | |||
2495 | } | |||
2496 | ||||
2497 | void AttributeOutputBase::EndTOX( const SwSection& rSect,bool bCareEnd ) | |||
2498 | { | |||
2499 | const SwTOXBase* pTOX = rSect.GetTOXBase(); | |||
2500 | if ( pTOX ) | |||
2501 | { | |||
2502 | ww::eField eCode = TOX_INDEX == pTOX->GetType() ? ww::eINDEX : ww::eTOC; | |||
2503 | GetExport( ).OutputField( nullptr, eCode, OUString(), FieldFlags::Close ); | |||
2504 | ||||
2505 | if ( pTOX->GetType() == TOX_INDEX && GetExport().AddSectionBreaksForTOX() ) | |||
2506 | { | |||
2507 | const SwFormatCol& rCol = rSect.GetFormat()->GetFormatAttr( RES_COL ); | |||
2508 | const SwColumns& rColumns = rCol.GetColumns(); | |||
2509 | sal_Int32 nCol = rColumns.size(); | |||
2510 | ||||
2511 | if ( 0 < nCol ) | |||
2512 | { | |||
2513 | WW8_SepInfo rInfo( &GetExport().m_rDoc.GetPageDesc( 0 ), rSect.GetFormat(), 0/*nRstLnNum*/ ); | |||
2514 | GetExport( ).AttrOutput().SectionBreak( msword::PageBreak, false, &rInfo ); | |||
2515 | } | |||
2516 | } | |||
2517 | } | |||
2518 | GetExport( ).m_bInWriteTOX = false; | |||
2519 | GetExport( ).m_bHideTabLeaderAndPageNumbers = false; | |||
2520 | if (bCareEnd) | |||
2521 | OnTOXEnding(); | |||
2522 | } | |||
2523 | ||||
2524 | bool MSWordExportBase::GetNumberFormat(const SwField& rField, OUString& rStr) | |||
2525 | { | |||
2526 | // Returns a date or time format string by using the US NfKeywordTable | |||
2527 | bool bHasFormat = false; | |||
2528 | SvNumberFormatter* pNFormatr = m_rDoc.GetNumberFormatter(); | |||
2529 | sal_uInt32 nFormatIdx = rField.GetFormat(); | |||
2530 | const SvNumberformat* pNumFormat = pNFormatr->GetEntry( nFormatIdx ); | |||
2531 | if( pNumFormat ) | |||
2532 | { | |||
2533 | LanguageType nLng = rField.GetLanguage(); | |||
2534 | LocaleDataWrapper aLocDat(pNFormatr->GetComponentContext(), | |||
2535 | LanguageTag(nLng)); | |||
2536 | ||||
2537 | OUString sFormat(pNumFormat->GetMappedFormatstring(GetNfKeywordTable(), | |||
2538 | aLocDat)); | |||
2539 | ||||
2540 | if (!sFormat.isEmpty()) | |||
2541 | { | |||
2542 | sw::ms::SwapQuotesInField(sFormat); | |||
2543 | ||||
2544 | rStr = "\\@\"" + sFormat + "\" " ; | |||
2545 | bHasFormat = true; | |||
2546 | } | |||
2547 | } | |||
2548 | return bHasFormat; | |||
2549 | } | |||
2550 | ||||
2551 | void AttributeOutputBase::GetNumberPara( OUString& rStr, const SwField& rField ) | |||
2552 | { | |||
2553 | switch(rField.GetFormat()) | |||
2554 | { | |||
2555 | case SVX_NUM_CHARS_UPPER_LETTER: | |||
2556 | case SVX_NUM_CHARS_UPPER_LETTER_N: | |||
2557 | rStr += "\\* ALPHABETIC "; | |||
2558 | break; | |||
2559 | case SVX_NUM_CHARS_LOWER_LETTER: | |||
2560 | case SVX_NUM_CHARS_LOWER_LETTER_N: | |||
2561 | rStr += "\\* alphabetic "; | |||
2562 | break; | |||
2563 | case SVX_NUM_ROMAN_UPPER: | |||
2564 | rStr += "\\* ROMAN "; | |||
2565 | break; | |||
2566 | case SVX_NUM_ROMAN_LOWER: | |||
2567 | rStr += "\\* roman "; | |||
2568 | break; | |||
2569 | default: | |||
2570 | OSL_ENSURE(rField.GetFormat() == SVX_NUM_ARABIC,do { if (true && (!(rField.GetFormat() == SVX_NUM_ARABIC ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "2571" ": "), "%s", "Unknown numbering type exported as default of Arabic" ); } } while (false) | |||
2571 | "Unknown numbering type exported as default of Arabic")do { if (true && (!(rField.GetFormat() == SVX_NUM_ARABIC ))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "2571" ": "), "%s", "Unknown numbering type exported as default of Arabic" ); } } while (false); | |||
2572 | [[fallthrough]]; | |||
2573 | case SVX_NUM_ARABIC: | |||
2574 | rStr += "\\* ARABIC "; | |||
2575 | break; | |||
2576 | case SVX_NUM_PAGEDESC: | |||
2577 | //Nothing, use word's default | |||
2578 | break; | |||
2579 | } | |||
2580 | } | |||
2581 | ||||
2582 | void WW8Export::WritePostItBegin( ww::bytes* pOut ) | |||
2583 | { | |||
2584 | sal_uInt8 aArr[ 3 ]; | |||
2585 | sal_uInt8* pArr = aArr; | |||
2586 | ||||
2587 | // sprmCFSpec true | |||
2588 | Set_UInt16( pArr, NS_sprm::CFSpec::val ); | |||
2589 | Set_UInt8( pArr, 1 ); | |||
2590 | ||||
2591 | m_pChpPlc->AppendFkpEntry( Strm().Tell() ); | |||
2592 | WriteChar( 0x05 ); // Annotation reference | |||
2593 | ||||
2594 | if( pOut ) | |||
2595 | pOut->insert( pOut->end(), aArr, pArr ); | |||
2596 | else | |||
2597 | m_pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr ); | |||
2598 | } | |||
2599 | ||||
2600 | OUString FieldString(ww::eField eIndex) | |||
2601 | { | |||
2602 | if (const char *pField = ww::GetEnglishFieldName(eIndex)) | |||
2603 | return " " + OUString::createFromAscii(pField) + " "; | |||
2604 | return " "; | |||
2605 | } | |||
2606 | ||||
2607 | void WW8AttributeOutput::HiddenField( const SwField& rField ) | |||
2608 | { | |||
2609 | //replace LF 0x0A with VT 0x0B | |||
2610 | const OUString sExpand(rField.GetPar2().replace(0x0A, 0x0B)); | |||
2611 | ||||
2612 | m_rWW8Export.m_pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell()); | |||
2613 | SwWW8Writer::WriteString16(m_rWW8Export.Strm(), sExpand, false); | |||
2614 | static sal_uInt8 aArr[] = | |||
2615 | { | |||
2616 | 0x3C, 0x08, 0x1 | |||
2617 | }; | |||
2618 | m_rWW8Export.m_pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell(), sizeof(aArr), aArr); | |||
2619 | } | |||
2620 | ||||
2621 | void WW8AttributeOutput::SetField( const SwField& rField, ww::eField eType, const OUString& rCmd ) | |||
2622 | { | |||
2623 | const SwSetExpField* pSet = static_cast<const SwSetExpField*>(&rField); | |||
2624 | const OUString &rVar = pSet->GetPar2(); | |||
2625 | ||||
2626 | sal_uLong nFrom = m_rWW8Export.Fc2Cp(m_rWW8Export.Strm().Tell()); | |||
2627 | ||||
2628 | GetExport().OutputField(&rField, eType, rCmd, FieldFlags::Start | | |||
2629 | FieldFlags::CmdStart | FieldFlags::CmdEnd); | |||
2630 | ||||
2631 | /* | |||
2632 | Is there a bookmark at the start position of this field, if so | |||
2633 | move it to the 0x14 of the result of the field. This is what word | |||
2634 | does. MoveFieldMarks moves any bookmarks at this position to | |||
2635 | the beginning of the field result, and marks the bookmark as a | |||
2636 | fieldbookmark which is to be ended before the field end mark | |||
2637 | instead of after it like a normal bookmark. | |||
2638 | */ | |||
2639 | m_rWW8Export.MoveFieldMarks(nFrom,m_rWW8Export.Fc2Cp(m_rWW8Export.Strm().Tell())); | |||
2640 | ||||
2641 | if (!rVar.isEmpty()) | |||
2642 | { | |||
2643 | SwWW8Writer::WriteString16(m_rWW8Export.Strm(), rVar, false); | |||
2644 | } | |||
2645 | GetExport().OutputField(&rField, eType, rCmd, FieldFlags::Close); | |||
2646 | } | |||
2647 | ||||
2648 | void WW8AttributeOutput::PostitField( const SwField* pField ) | |||
2649 | { | |||
2650 | const SwPostItField *pPField = static_cast<const SwPostItField*>(pField); | |||
2651 | m_rWW8Export.m_pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pPField ); | |||
2652 | m_rWW8Export.WritePostItBegin( m_rWW8Export.pO.get() ); | |||
2653 | } | |||
2654 | ||||
2655 | bool WW8AttributeOutput::DropdownField( const SwField* pField ) | |||
2656 | { | |||
2657 | const SwDropDownField& rField2 = *static_cast<const SwDropDownField*>(pField); | |||
2658 | uno::Sequence<OUString> aItems = | |||
2659 | rField2.GetItemSequence(); | |||
2660 | GetExport().DoComboBox(rField2.GetName(), | |||
2661 | rField2.GetHelp(), | |||
2662 | rField2.GetToolTip(), | |||
2663 | rField2.GetSelectedItem(), aItems); | |||
2664 | return false; | |||
2665 | } | |||
2666 | ||||
2667 | bool WW8AttributeOutput::PlaceholderField( const SwField* ) | |||
2668 | { | |||
2669 | return true; // expand to text? | |||
2670 | } | |||
2671 | ||||
2672 | void WW8AttributeOutput::RefField( const SwField &rField, const OUString &rRef) | |||
2673 | { | |||
2674 | const OUString sStr{ FieldString( ww::eREF ) + "\"" + rRef + "\" " }; | |||
2675 | m_rWW8Export.OutputField( &rField, ww::eREF, sStr, FieldFlags::Start | | |||
2676 | FieldFlags::CmdStart | FieldFlags::CmdEnd ); | |||
2677 | const OUString sVar = lcl_GetExpandedField( rField ); | |||
2678 | if ( !sVar.isEmpty() ) | |||
2679 | { | |||
2680 | SwWW8Writer::WriteString16( m_rWW8Export.Strm(), sVar, false ); | |||
2681 | } | |||
2682 | m_rWW8Export.OutputField( &rField, ww::eREF, sStr, FieldFlags::Close ); | |||
2683 | } | |||
2684 | ||||
2685 | void WW8AttributeOutput::WriteExpand( const SwField* pField ) | |||
2686 | { | |||
2687 | SwWW8Writer::WriteString16( m_rWW8Export.Strm(), lcl_GetExpandedField( *pField ), false ); | |||
2688 | } | |||
2689 | ||||
2690 | namespace | |||
2691 | { | |||
2692 | // Escapes a token string for storing in Word formats. Its import counterpart | |||
2693 | // is lcl_ExtractToken in writerfilter/source/dmapper/DomainMapper_Impl.cxx | |||
2694 | OUString EscapeToken(const OUString& rCommand) | |||
2695 | { | |||
2696 | bool bWasEscaped = false; | |||
2697 | ||||
2698 | const int nBufferLen = rCommand.getLength()*1.5; | |||
2699 | OUStringBuffer sResult(nBufferLen); | |||
2700 | sResult.append('"'); // opening quote | |||
2701 | for (sal_Int32 i = 0; i < rCommand.getLength(); ++i) | |||
2702 | { | |||
2703 | sal_Unicode ch = rCommand[i]; | |||
2704 | switch (ch) | |||
2705 | { | |||
2706 | case '\\': | |||
2707 | case '"': | |||
2708 | // Backslashes and doublequotes must be escaped | |||
2709 | bWasEscaped = true; | |||
2710 | sResult.append('\\'); | |||
2711 | break; | |||
2712 | case ' ': | |||
2713 | // Spaces require quotation | |||
2714 | bWasEscaped = true; | |||
2715 | break; | |||
2716 | } | |||
2717 | sResult.append(ch); | |||
2718 | } | |||
2719 | ||||
2720 | if (bWasEscaped) | |||
2721 | { | |||
2722 | sResult.append('"'); // closing quote | |||
2723 | return sResult.makeStringAndClear(); | |||
2724 | } | |||
2725 | // No escapement/quotation was required | |||
2726 | return rCommand; | |||
2727 | } | |||
2728 | } | |||
2729 | ||||
2730 | void AttributeOutputBase::TextField( const SwFormatField& rField ) | |||
2731 | { | |||
2732 | const SwField* pField = rField.GetField(); | |||
2733 | bool bWriteExpand = false; | |||
2734 | const sal_uInt16 nSubType = pField->GetSubType(); | |||
2735 | ||||
2736 | switch (pField->GetTyp()->Which()) | |||
2737 | { | |||
2738 | case SwFieldIds::GetExp: | |||
2739 | if (nSubType == nsSwGetSetExpType::GSE_STRING) | |||
2740 | { | |||
2741 | const SwGetExpField *pGet = static_cast<const SwGetExpField*>(pField); | |||
2742 | RefField( *pGet, pGet->GetFormula() ); | |||
2743 | } | |||
2744 | else | |||
2745 | bWriteExpand = true; | |||
2746 | break; | |||
2747 | case SwFieldIds::SetExp: | |||
2748 | if (nsSwGetSetExpType::GSE_SEQ == nSubType) | |||
2749 | { | |||
2750 | OUString sStr; | |||
2751 | if (GetExport().FieldsQuoted()) | |||
2752 | sStr = FieldString(ww::eSEQ) + pField->GetTyp()->GetName() + " "; | |||
2753 | else | |||
2754 | sStr = FieldString(ww::eSEQ) + "\"" + pField->GetTyp()->GetName() +"\" "; | |||
2755 | GetNumberPara( sStr, *pField ); | |||
2756 | GetExport().OutputField(pField, ww::eSEQ, sStr); | |||
2757 | } | |||
2758 | else if (nSubType & nsSwGetSetExpType::GSE_STRING) | |||
2759 | { | |||
2760 | bool bShowAsWell = false; | |||
2761 | ww::eField eFieldNo; | |||
2762 | const SwSetExpField *pSet = static_cast<const SwSetExpField*>(pField); | |||
2763 | const OUString sVar = pSet->GetPar2(); | |||
2764 | OUString sStr; | |||
2765 | if (pSet->GetInputFlag()) | |||
2766 | { | |||
2767 | sStr = FieldString(ww::eASK) + "\"" | |||
2768 | + pSet->GetPar1() + "\" " | |||
2769 | + pSet->GetPromptText() + " \\d " | |||
2770 | + sVar; | |||
2771 | eFieldNo = ww::eASK; | |||
2772 | } | |||
2773 | else | |||
2774 | { | |||
2775 | sStr = FieldString(ww::eSET) | |||
2776 | + pSet->GetPar1() + " \"" | |||
2777 | + sVar + "\" "; | |||
2778 | eFieldNo = ww::eSET; | |||
2779 | bShowAsWell = (nSubType & nsSwExtendedSubType::SUB_INVISIBLE) == 0; | |||
2780 | } | |||
2781 | ||||
2782 | SetField( *pField, eFieldNo, sStr ); | |||
2783 | ||||
2784 | if (bShowAsWell) | |||
2785 | RefField( *pSet, pSet->GetPar1() ); | |||
2786 | } | |||
2787 | else | |||
2788 | bWriteExpand = true; | |||
2789 | break; | |||
2790 | case SwFieldIds::PageNumber: | |||
2791 | { | |||
2792 | OUString sStr = FieldString(ww::ePAGE); | |||
2793 | GetNumberPara(sStr, *pField); | |||
2794 | GetExport().OutputField(pField, ww::ePAGE, sStr); | |||
2795 | } | |||
2796 | break; | |||
2797 | case SwFieldIds::Filename: | |||
2798 | { | |||
2799 | OUString sStr = FieldString(ww::eFILENAME); | |||
2800 | if (pField->GetFormat() == FF_PATHNAME) | |||
2801 | sStr += "\\p "; | |||
2802 | GetExport().OutputField(pField, ww::eFILENAME, sStr); | |||
2803 | } | |||
2804 | break; | |||
2805 | case SwFieldIds::Database: | |||
2806 | { | |||
2807 | OUString sStr = FieldString(ww::eMERGEFIELD) | |||
2808 | + EscapeToken(static_cast<SwDBFieldType *>(pField->GetTyp())->GetColumnName()) + " "; | |||
2809 | GetExport().OutputField(pField, ww::eMERGEFIELD, sStr); | |||
2810 | } | |||
2811 | break; | |||
2812 | case SwFieldIds::DatabaseName: | |||
2813 | { | |||
2814 | SwDBData aData = GetExport().m_rDoc.GetDBData(); | |||
2815 | const OUString sStr = FieldString(ww::eDATABASE) | |||
2816 | + aData.sDataSource | |||
2817 | + OUStringChar(DB_DELIMu'\x00ff') | |||
2818 | + aData.sCommand; | |||
2819 | GetExport().OutputField(pField, ww::eDATABASE, sStr); | |||
2820 | } | |||
2821 | break; | |||
2822 | case SwFieldIds::Author: | |||
2823 | { | |||
2824 | ww::eField eField = | |||
2825 | ((AF_SHORTCUT & pField->GetFormat()) ? ww::eUSERINITIALS : ww::eUSERNAME); | |||
2826 | GetExport().OutputField(pField, eField, FieldString(eField)); | |||
2827 | } | |||
2828 | break; | |||
2829 | case SwFieldIds::TemplateName: | |||
2830 | GetExport().OutputField(pField, ww::eTEMPLATE, FieldString(ww::eTEMPLATE)); | |||
2831 | break; | |||
2832 | case SwFieldIds::DocInfo: // Last printed, last edited,... | |||
2833 | if( DI_SUB_FIXED & nSubType ) | |||
2834 | bWriteExpand = true; | |||
2835 | else | |||
2836 | { | |||
2837 | OUString sStr; | |||
2838 | ww::eField eField(ww::eNONE); | |||
2839 | switch (0xff & nSubType) | |||
2840 | { | |||
2841 | case DI_TITLE: | |||
2842 | eField = ww::eTITLE; | |||
2843 | break; | |||
2844 | case DI_SUBJECT: | |||
2845 | eField = ww::eSUBJECT; | |||
2846 | break; | |||
2847 | case DI_KEYS: | |||
2848 | eField = ww::eKEYWORDS; | |||
2849 | break; | |||
2850 | case DI_COMMENT: | |||
2851 | eField = ww::eCOMMENTS; | |||
2852 | break; | |||
2853 | case DI_DOCNO: | |||
2854 | eField = ww::eREVNUM; | |||
2855 | break; | |||
2856 | case DI_CREATE: | |||
2857 | if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK)) | |||
2858 | eField = ww::eAUTHOR; | |||
2859 | else if (GetExport().GetNumberFormat(*pField, sStr)) | |||
2860 | eField = ww::eCREATEDATE; | |||
2861 | break; | |||
2862 | ||||
2863 | case DI_CHANGE: | |||
2864 | if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK)) | |||
2865 | eField = ww::eLASTSAVEDBY; | |||
2866 | else if (GetExport().GetNumberFormat(*pField, sStr)) | |||
2867 | eField = ww::eSAVEDATE; | |||
2868 | break; | |||
2869 | ||||
2870 | case DI_PRINT: | |||
2871 | if (DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK) && | |||
2872 | GetExport().GetNumberFormat(*pField, sStr)) | |||
2873 | eField = ww::ePRINTDATE; | |||
2874 | break; | |||
2875 | case DI_EDIT: | |||
2876 | if( DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK ) && | |||
2877 | GetExport().GetNumberFormat( *pField, sStr )) | |||
2878 | eField = ww::eSAVEDATE; | |||
2879 | else | |||
2880 | eField = ww::eEDITTIME; | |||
2881 | break; | |||
2882 | case DI_CUSTOM: | |||
2883 | eField = ww::eDOCPROPERTY; | |||
2884 | { | |||
2885 | const SwDocInfoField * pDocInfoField = | |||
2886 | dynamic_cast<const SwDocInfoField *> (pField); | |||
2887 | ||||
2888 | if (pDocInfoField != nullptr) | |||
2889 | { | |||
2890 | OUString sFieldname = pDocInfoField->GetFieldName(); | |||
2891 | ||||
2892 | const sal_Int32 nIndex = sFieldname.indexOf(':'); | |||
2893 | if (nIndex >= 0) | |||
2894 | sFieldname = sFieldname.copy(nIndex + 1); | |||
2895 | ||||
2896 | sStr = "\"" + sFieldname + "\""; | |||
2897 | } | |||
2898 | } | |||
2899 | break; | |||
2900 | default: | |||
2901 | break; | |||
2902 | } | |||
2903 | ||||
2904 | if (eField != ww::eNONE) | |||
2905 | { | |||
2906 | GetExport().OutputField(pField, eField, FieldString(eField) + sStr); | |||
2907 | } | |||
2908 | else | |||
2909 | bWriteExpand = true; | |||
2910 | } | |||
2911 | break; | |||
2912 | case SwFieldIds::DateTime: | |||
2913 | { | |||
2914 | OUString sStr; | |||
2915 | if (!GetExport().GetNumberFormat(*pField, sStr)) | |||
2916 | bWriteExpand = true; | |||
2917 | else | |||
2918 | { | |||
2919 | ww::eField eField = (DATEFLD & nSubType) ? ww::eDATE : ww::eTIME; | |||
2920 | GetExport().OutputField(pField, eField, FieldString(eField) + sStr); | |||
2921 | } | |||
2922 | } | |||
2923 | break; | |||
2924 | case SwFieldIds::DocStat: | |||
2925 | { | |||
2926 | ww::eField eField = ww::eNONE; | |||
2927 | ||||
2928 | switch (nSubType) | |||
2929 | { | |||
2930 | case DS_PAGE: | |||
2931 | eField = ww::eNUMPAGES; | |||
2932 | break; | |||
2933 | case DS_WORD: | |||
2934 | eField = ww::eNUMWORDS; | |||
2935 | break; | |||
2936 | case DS_CHAR: | |||
2937 | eField = ww::eNUMCHARS; | |||
2938 | break; | |||
2939 | } | |||
2940 | ||||
2941 | if (eField != ww::eNONE) | |||
2942 | { | |||
2943 | OUString sStr = FieldString(eField); | |||
2944 | GetNumberPara(sStr, *pField); | |||
2945 | GetExport().OutputField(pField, eField, sStr); | |||
2946 | } | |||
2947 | else | |||
2948 | bWriteExpand = true; | |||
2949 | } | |||
2950 | break; | |||
2951 | case SwFieldIds::ExtUser: | |||
2952 | { | |||
2953 | ww::eField eField = ww::eNONE; | |||
2954 | switch (0xFF & nSubType) | |||
2955 | { | |||
2956 | case EU_FIRSTNAME: | |||
2957 | case EU_NAME: | |||
2958 | eField = ww::eUSERNAME; | |||
2959 | break; | |||
2960 | case EU_SHORTCUT: | |||
2961 | eField = ww::eUSERINITIALS; | |||
2962 | break; | |||
2963 | case EU_STREET: | |||
2964 | case EU_COUNTRY: | |||
2965 | case EU_ZIP: | |||
2966 | case EU_CITY: | |||
2967 | eField = ww::eUSERADDRESS; | |||
2968 | break; | |||
2969 | } | |||
2970 | ||||
2971 | if (eField != ww::eNONE) | |||
2972 | { | |||
2973 | GetExport().OutputField(pField, eField, FieldString(eField)); | |||
2974 | } | |||
2975 | else | |||
2976 | bWriteExpand = true; | |||
2977 | } | |||
2978 | break; | |||
2979 | case SwFieldIds::TableOfAuthorities: | |||
2980 | { | |||
2981 | OUString sRet(static_cast<SwAuthorityField const*>(pField) | |||
2982 | ->ExpandCitation(AUTH_FIELD_IDENTIFIER, nullptr)); | |||
2983 | // FIXME: DomainMapper_Impl::CloseFieldCommand() stuffs fully formed | |||
2984 | // field instructions in here, but if the field doesn't originate | |||
2985 | // from those filters it won't have that | |||
2986 | if (!sRet.trim().startsWith("CITATION")) | |||
2987 | { | |||
2988 | sRet = FieldString(ww::eCITATION) + " \"" + sRet + "\""; | |||
2989 | } | |||
2990 | GetExport().OutputField( pField, ww::eCITATION, sRet ); | |||
2991 | } | |||
2992 | break; | |||
2993 | case SwFieldIds::Postit: | |||
2994 | //Sadly only possible for word in main document text | |||
2995 | if (GetExport().m_nTextTyp == TXT_MAINTEXT) | |||
2996 | { | |||
2997 | PostitField( pField ); | |||
2998 | } | |||
2999 | break; | |||
3000 | case SwFieldIds::Input: | |||
3001 | { | |||
3002 | const SwInputField * pInputField = dynamic_cast<const SwInputField *>(pField); | |||
3003 | ||||
3004 | if (pInputField && pInputField->isFormField()) | |||
3005 | GetExport().DoFormText(pInputField); | |||
3006 | else | |||
3007 | { | |||
3008 | const OUString sStr = FieldString(ww::eFILLIN) + "\"" | |||
3009 | + pField->GetPar2() + "\""; | |||
3010 | ||||
3011 | GetExport().OutputField(pField, ww::eFILLIN, sStr); | |||
3012 | } | |||
3013 | } | |||
3014 | break; | |||
3015 | case SwFieldIds::GetRef: | |||
3016 | { | |||
3017 | ww::eField eField = ww::eNONE; | |||
3018 | OUString sStr; | |||
3019 | const SwGetRefField& rRField = *static_cast<const SwGetRefField*>(pField); | |||
3020 | switch (nSubType) | |||
3021 | { | |||
3022 | case REF_SETREFATTR: | |||
3023 | case REF_BOOKMARK: | |||
3024 | switch (pField->GetFormat()) | |||
3025 | { | |||
3026 | case REF_PAGE_PGDESC: | |||
3027 | case REF_PAGE: | |||
3028 | eField = ww::ePAGEREF; | |||
3029 | break; | |||
3030 | default: | |||
3031 | eField = ww::eREF; | |||
3032 | break; | |||
3033 | } | |||
3034 | { | |||
3035 | const OUString& aRefName(rRField.GetSetRefName()); | |||
3036 | sStr = FieldString(eField) | |||
3037 | + MSWordExportBase::GetBookmarkName(nSubType, &aRefName, 0); | |||
3038 | } | |||
3039 | switch (pField->GetFormat()) | |||
3040 | { | |||
3041 | case REF_NUMBER: | |||
3042 | sStr += " \\r"; | |||
3043 | break; | |||
3044 | case REF_NUMBER_NO_CONTEXT: | |||
3045 | sStr += " \\n"; | |||
3046 | break; | |||
3047 | case REF_NUMBER_FULL_CONTEXT: | |||
3048 | sStr += " \\w"; | |||
3049 | break; | |||
3050 | } | |||
3051 | break; | |||
3052 | case REF_SEQUENCEFLD: | |||
3053 | { | |||
3054 | // Not implemented for RTF | |||
3055 | if(GetExport().GetExportFormat() == MSWordExportBase::ExportFormat::RTF) | |||
3056 | break; | |||
3057 | ||||
3058 | switch (pField->GetFormat()) | |||
3059 | { | |||
3060 | case REF_PAGE: | |||
3061 | case REF_PAGE_PGDESC: | |||
3062 | eField = ww::ePAGEREF; | |||
3063 | break; | |||
3064 | default: | |||
3065 | eField = ww::eREF; | |||
3066 | break; | |||
3067 | } | |||
3068 | // Generate a unique bookmark name | |||
3069 | { | |||
3070 | OUString sName{rRField.GetSetRefName() + OUString::number(rRField.GetSeqNo())}; | |||
3071 | switch (pField->GetFormat()) | |||
3072 | { | |||
3073 | case REF_PAGE: | |||
3074 | case REF_PAGE_PGDESC: | |||
3075 | case REF_CONTENT: | |||
3076 | case REF_UPDOWN: | |||
3077 | sName += "_full"; | |||
3078 | break; | |||
3079 | case REF_ONLYNUMBER: | |||
3080 | sName += "_label_and_number"; | |||
3081 | break; | |||
3082 | case REF_ONLYCAPTION: | |||
3083 | sName += "_caption_only"; | |||
3084 | break; | |||
3085 | case REF_ONLYSEQNO: | |||
3086 | sName += "_number_only"; | |||
3087 | break; | |||
3088 | default: // Ignore other types of reference fields | |||
3089 | eField = ww::eNONE; | |||
3090 | break; | |||
3091 | } | |||
3092 | sStr = FieldString(eField) + MSWordExportBase::GetBookmarkName(nSubType, &sName, 0); | |||
3093 | } | |||
3094 | switch (pField->GetFormat()) | |||
3095 | { | |||
3096 | case REF_NUMBER: | |||
3097 | sStr += " \\r"; | |||
3098 | break; | |||
3099 | case REF_NUMBER_NO_CONTEXT: | |||
3100 | sStr += " \\n"; | |||
3101 | break; | |||
3102 | case REF_NUMBER_FULL_CONTEXT: | |||
3103 | sStr += " \\w"; | |||
3104 | break; | |||
3105 | } | |||
3106 | break; | |||
3107 | } | |||
3108 | case REF_FOOTNOTE: | |||
3109 | case REF_ENDNOTE: | |||
3110 | switch (pField->GetFormat()) | |||
3111 | { | |||
3112 | case REF_PAGE_PGDESC: | |||
3113 | case REF_PAGE: | |||
3114 | eField = ww::ePAGEREF; | |||
3115 | break; | |||
3116 | case REF_UPDOWN: | |||
3117 | eField = ww::eREF; | |||
3118 | break; | |||
3119 | default: | |||
3120 | eField = | |||
3121 | REF_ENDNOTE == nSubType ? ww::eNOTEREF : ww::eFOOTREF; | |||
3122 | break; | |||
3123 | } | |||
3124 | sStr = FieldString(eField) | |||
3125 | + MSWordExportBase::GetBookmarkName(nSubType, nullptr, rRField.GetSeqNo()); | |||
3126 | break; | |||
3127 | } | |||
3128 | ||||
3129 | if (eField != ww::eNONE) | |||
3130 | { | |||
3131 | switch (pField->GetFormat()) | |||
3132 | { | |||
3133 | case REF_UPDOWN: | |||
3134 | sStr += " \\p \\h "; // with hyperlink | |||
3135 | break; | |||
3136 | case REF_CHAPTER: | |||
3137 | sStr += " \\n \\h "; // with hyperlink | |||
3138 | break; | |||
3139 | default: | |||
3140 | sStr += " \\h "; // insert hyperlink | |||
3141 | break; | |||
3142 | } | |||
3143 | GetExport().OutputField(pField, eField, sStr); | |||
3144 | } | |||
3145 | else | |||
3146 | bWriteExpand = true; | |||
3147 | } | |||
3148 | break; | |||
3149 | case SwFieldIds::CombinedChars: | |||
3150 | { | |||
3151 | /* | |||
3152 | We need a font size to fill in the defaults, if these are overridden | |||
3153 | (as they generally are) by character properties then those properties | |||
3154 | win. | |||
3155 | ||||
3156 | The fontsize that is used in MS for determining the defaults is always | |||
3157 | the CJK fontsize even if the text is not in that language, in OOo the | |||
3158 | largest fontsize used in the field is the one we should take, but | |||
3159 | whatever we do, word will actually render using the fontsize set for | |||
3160 | CJK text. Nevertheless we attempt to guess whether the script is in | |||
3161 | asian or western text based up on the first character and use the | |||
3162 | font size of that script as our default. | |||
3163 | */ | |||
3164 | assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is())(static_cast <bool> (g_pBreakIt && g_pBreakIt-> GetBreakIter().is()) ? void (0) : __assert_fail ("g_pBreakIt && g_pBreakIt->GetBreakIter().is()" , "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 3164, __extension__ __PRETTY_FUNCTION__)); | |||
3165 | sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType( pField->GetPar1(), 0); | |||
3166 | ||||
3167 | long nHeight = static_cast<const SvxFontHeightItem&>((GetExport().GetItem( | |||
3168 | GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript)))).GetHeight(); | |||
3169 | ||||
3170 | nHeight = (nHeight + 10) / 20; //Font Size in points; | |||
3171 | ||||
3172 | /* | |||
3173 | Divide the combined char string into its up and down part. Get the | |||
3174 | font size and fill in the defaults as up == half the font size and | |||
3175 | down == a fifth the font size | |||
3176 | */ | |||
3177 | const sal_Int32 nAbove = (pField->GetPar1().getLength()+1)/2; | |||
3178 | const OUString sStr = FieldString(ww::eEQ) | |||
3179 | + "\\o (\\s\\up " | |||
3180 | + OUString::number(nHeight/2) | |||
3181 | + "(" | |||
3182 | + pField->GetPar1().copy(0, nAbove) | |||
3183 | + "), \\s\\do " | |||
3184 | + OUString::number(nHeight/5) | |||
3185 | + "(" | |||
3186 | + pField->GetPar1().copy(nAbove) | |||
3187 | + "))"; | |||
3188 | GetExport().OutputField(pField, ww::eEQ, sStr); | |||
3189 | } | |||
3190 | break; | |||
3191 | case SwFieldIds::Dropdown: | |||
3192 | bWriteExpand = DropdownField( pField ); | |||
3193 | break; | |||
3194 | case SwFieldIds::Chapter: | |||
3195 | bWriteExpand = true; | |||
3196 | if (GetExport().m_bOutKF && rField.GetTextField()) | |||
3197 | { | |||
3198 | const SwTextNode *pTextNd = GetExport().GetHdFtPageRoot(); | |||
3199 | if (!pTextNd) | |||
3200 | { | |||
3201 | pTextNd = GetExport().m_pCurPam->GetNode().GetTextNode(); | |||
3202 | } | |||
3203 | ||||
3204 | if (pTextNd) | |||
3205 | { | |||
3206 | SwChapterField aCopy(*static_cast<const SwChapterField*>(pField)); | |||
3207 | aCopy.ChangeExpansion(*pTextNd, false); | |||
3208 | const OUString sStr = FieldString(ww::eSTYLEREF) | |||
3209 | + " " | |||
3210 | + OUString::number(aCopy.GetLevel() + 1) | |||
3211 | + " \\* MERGEFORMAT "; | |||
3212 | GetExport().OutputField(pField, ww::eSTYLEREF, sStr); | |||
3213 | bWriteExpand = false; | |||
3214 | } | |||
3215 | } | |||
3216 | break; | |||
3217 | case SwFieldIds::HiddenText: | |||
3218 | { | |||
3219 | OUString sExpand(pField->GetPar2()); | |||
3220 | if (!sExpand.isEmpty()) | |||
3221 | { | |||
3222 | HiddenField( *pField ); | |||
3223 | } | |||
3224 | } | |||
3225 | break; | |||
3226 | case SwFieldIds::JumpEdit: | |||
3227 | bWriteExpand = PlaceholderField( pField ); | |||
3228 | break; | |||
3229 | case SwFieldIds::Macro: | |||
3230 | { | |||
3231 | const OUString sStr = " MACROBUTTON" | |||
3232 | + pField->GetPar1().replaceFirst("StarOffice.Standard.Modul1.", " ") | |||
3233 | + " " | |||
3234 | + lcl_GetExpandedField(*pField); | |||
3235 | GetExport().OutputField( pField, ww::eMACROBUTTON, sStr ); | |||
3236 | } | |||
3237 | break; | |||
3238 | case SwFieldIds::Table: | |||
3239 | { | |||
3240 | ww::eField eField = ww::eEquals; | |||
3241 | OUString aExpand = " =" + pField->GetFieldName().trim(); | |||
3242 | GetExport().OutputField(pField, eField, aExpand); | |||
3243 | } | |||
3244 | break; | |||
3245 | case SwFieldIds::User: | |||
3246 | { | |||
3247 | ww::eField eField = ww::eDOCVARIABLE; | |||
3248 | OUString aExpand = FieldString(eField) + pField->GetPar1() + " "; | |||
3249 | GetExport().OutputField(pField, eField, aExpand); | |||
3250 | } | |||
3251 | break; | |||
3252 | default: | |||
3253 | bWriteExpand = true; | |||
3254 | break; | |||
3255 | } | |||
3256 | ||||
3257 | if (bWriteExpand) | |||
3258 | WriteExpand( pField ); | |||
3259 | } | |||
3260 | ||||
3261 | void AttributeOutputBase::TextFlyContent( const SwFormatFlyCnt& rFlyContent ) | |||
3262 | { | |||
3263 | if ( auto pTextNd = dynamic_cast< const SwContentNode *>( GetExport().m_pOutFormatNode ) ) | |||
3264 | { | |||
3265 | Point const origin; | |||
3266 | Point aLayPos = pTextNd->FindLayoutRect( false, &origin ).Pos(); | |||
3267 | ||||
3268 | SwPosition aPos( *pTextNd ); | |||
3269 | ww8::Frame aFrame( *rFlyContent.GetFrameFormat(), aPos ); | |||
3270 | ||||
3271 | OutputFlyFrame_Impl( aFrame, aLayPos ); | |||
3272 | } | |||
3273 | } | |||
3274 | ||||
3275 | // TOXMarks are still missing | |||
3276 | ||||
3277 | // WW allows detailed settings for hyphenation only for the whole document. | |||
3278 | // One could implement following mimic: The values of the style "Standard" will | |||
3279 | // be set in the Document Properties ( DOP ) if they exist. | |||
3280 | ||||
3281 | // ACK. This suggestion fits exactly to our implementation of the import, | |||
3282 | // therefore I'll implement that right now. (KHZ, 07/15/2000) | |||
3283 | void WW8AttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone ) | |||
3284 | { | |||
3285 | // sprmPFNoAutoHyph | |||
3286 | m_rWW8Export.InsUInt16( NS_sprm::PFNoAutoHyph::val ); | |||
3287 | ||||
3288 | m_rWW8Export.pO->push_back( rHyphenZone.IsHyphen() ? 0 : 1 ); | |||
3289 | } | |||
3290 | ||||
3291 | void WW8AttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace ) | |||
3292 | { | |||
3293 | m_rWW8Export.InsUInt16( NS_sprm::PFAutoSpaceDE::val ); | |||
3294 | m_rWW8Export.pO->push_back( rScriptSpace.GetValue() ? 1 : 0 ); | |||
3295 | } | |||
3296 | ||||
3297 | void WW8AttributeOutput::ParaHangingPunctuation( const SfxBoolItem& rItem ) | |||
3298 | { | |||
3299 | m_rWW8Export.InsUInt16( NS_sprm::PFOverflowPunct::val ); | |||
3300 | m_rWW8Export.pO->push_back( rItem.GetValue() ? 1 : 0 ); | |||
3301 | } | |||
3302 | ||||
3303 | void WW8AttributeOutput::ParaForbiddenRules( const SfxBoolItem& rItem ) | |||
3304 | { | |||
3305 | m_rWW8Export.InsUInt16( NS_sprm::PFKinsoku::val ); | |||
3306 | m_rWW8Export.pO->push_back( rItem.GetValue() ? 1 : 0 ); | |||
3307 | } | |||
3308 | ||||
3309 | void WW8AttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid ) | |||
3310 | { | |||
3311 | // sprmPFUsePgsuSettings | |||
3312 | ||||
3313 | m_rWW8Export.InsUInt16( NS_sprm::PFUsePgsuSettings::val ); | |||
3314 | m_rWW8Export.pO->push_back( rGrid.GetValue() ? 1 : 0 ); | |||
3315 | } | |||
3316 | ||||
3317 | void WW8AttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign ) | |||
3318 | { | |||
3319 | // sprmPWAlignFont | |||
3320 | ||||
3321 | m_rWW8Export.InsUInt16( NS_sprm::PWAlignFont::val ); | |||
3322 | ||||
3323 | SvxParaVertAlignItem::Align nAlign = rAlign.GetValue(); | |||
3324 | sal_uInt16 nVal; | |||
3325 | switch ( nAlign ) | |||
3326 | { | |||
3327 | case SvxParaVertAlignItem::Align::Baseline: | |||
3328 | nVal = 2; | |||
3329 | break; | |||
3330 | case SvxParaVertAlignItem::Align::Top: | |||
3331 | nVal = 0; | |||
3332 | break; | |||
3333 | case SvxParaVertAlignItem::Align::Center: | |||
3334 | nVal = 1; | |||
3335 | break; | |||
3336 | case SvxParaVertAlignItem::Align::Bottom: | |||
3337 | nVal = 3; | |||
3338 | break; | |||
3339 | case SvxParaVertAlignItem::Align::Automatic: | |||
3340 | nVal = 4; | |||
3341 | break; | |||
3342 | default: | |||
3343 | nVal = 4; | |||
3344 | OSL_FAIL( "Unknown vert alignment" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "3344" ": "), "%s", "Unknown vert alignment"); } } while (false); | |||
3345 | break; | |||
3346 | } | |||
3347 | m_rWW8Export.InsUInt16( nVal ); | |||
3348 | } | |||
3349 | ||||
3350 | // NoHyphen: I didn't find an equal in the SW UI and WW UI | |||
3351 | ||||
3352 | // RefMark, NoLineBreakHere are still missing | |||
3353 | ||||
3354 | void WW8Export::WriteFootnoteBegin( const SwFormatFootnote& rFootnote, ww::bytes* pOutArr ) | |||
3355 | { | |||
3356 | ww::bytes aAttrArr; | |||
3357 | const bool bAutoNum = rFootnote.GetNumStr().isEmpty(); | |||
3358 | if( bAutoNum ) | |||
3359 | { | |||
3360 | static const sal_uInt8 aSpec[] = | |||
3361 | { | |||
3362 | 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation | |||
3363 | 0x55, 0x08, 1 // sprmCFSpec | |||
3364 | }; | |||
3365 | ||||
3366 | aAttrArr.insert(aAttrArr.end(), aSpec, aSpec+sizeof(aSpec)); | |||
3367 | } | |||
3368 | ||||
3369 | // sprmCIstd | |||
3370 | const SwEndNoteInfo* pInfo; | |||
3371 | if( rFootnote.IsEndNote() ) | |||
3372 | pInfo = &m_rDoc.GetEndNoteInfo(); | |||
3373 | else | |||
3374 | pInfo = &m_rDoc.GetFootnoteInfo(); | |||
3375 | const SwCharFormat* pCFormat = pOutArr | |||
3376 | ? pInfo->GetAnchorCharFormat( m_rDoc ) | |||
3377 | : pInfo->GetCharFormat( m_rDoc ); | |||
3378 | SwWW8Writer::InsUInt16( aAttrArr, NS_sprm::CIstd::val ); | |||
3379 | SwWW8Writer::InsUInt16( aAttrArr, GetId( pCFormat ) ); | |||
3380 | ||||
3381 | // fSpec-Attribut true | |||
3382 | // For Auto-Number a special character must go | |||
3383 | // into the text and therefore a fSpec attribute | |||
3384 | m_pChpPlc->AppendFkpEntry( Strm().Tell() ); | |||
3385 | if( bAutoNum ) | |||
3386 | WriteChar( 0x02 ); // auto number character | |||
3387 | else | |||
3388 | // user numbering | |||
3389 | OutSwString(rFootnote.GetNumStr(), 0, rFootnote.GetNumStr().getLength()); | |||
3390 | ||||
3391 | if( pOutArr ) | |||
3392 | { | |||
3393 | // insert at start of array, so the "hard" attribute overrule the | |||
3394 | // attributes of the character template | |||
3395 | pOutArr->insert( pOutArr->begin(), aAttrArr.begin(), aAttrArr.end() ); | |||
3396 | } | |||
3397 | else | |||
3398 | { | |||
3399 | std::unique_ptr<ww::bytes> pOwnOutArr(new ww::bytes); | |||
3400 | ||||
3401 | // insert at start of array, so the "hard" attribute overrule the | |||
3402 | // attributes of the character template | |||
3403 | pOwnOutArr->insert(pOwnOutArr->begin(), aAttrArr.begin(), aAttrArr.end()); | |||
3404 | ||||
3405 | // write for the ftn number in the content, the font of the anchor | |||
3406 | const SwTextFootnote* pTextFootnote = rFootnote.GetTextFootnote(); | |||
3407 | if( pTextFootnote ) | |||
3408 | { | |||
3409 | std::unique_ptr<ww::bytes> pOld = std::move(pO); | |||
3410 | pO = std::move(pOwnOutArr); | |||
3411 | SfxItemSet aSet( m_rDoc.GetAttrPool(), svl::Items<RES_CHRATR_FONT, | |||
3412 | RES_CHRATR_FONT>{} ); | |||
3413 | ||||
3414 | pCFormat = pInfo->GetCharFormat( m_rDoc ); | |||
3415 | ||||
3416 | pTextFootnote->GetTextNode().GetParaAttr(aSet, | |||
3417 | pTextFootnote->GetStart(), pTextFootnote->GetStart() + 1, true); | |||
3418 | if (aSet.Count()) | |||
3419 | { | |||
3420 | m_pAttrOutput->OutputItem( aSet.Get( RES_CHRATR_FONT ) ); | |||
3421 | } | |||
3422 | else | |||
3423 | { | |||
3424 | m_pAttrOutput->OutputItem( pCFormat->GetAttrSet().Get(RES_CHRATR_FONT) ); | |||
3425 | } | |||
3426 | pOwnOutArr = std::move(pO); | |||
3427 | pO = std::move(pOld); | |||
3428 | } | |||
3429 | m_pChpPlc->AppendFkpEntry( Strm().Tell(), pOwnOutArr->size(), | |||
3430 | pOwnOutArr->data() ); | |||
3431 | } | |||
3432 | } | |||
3433 | ||||
3434 | static bool lcl_IsAtTextEnd(const SwFormatFootnote& rFootnote) | |||
3435 | { | |||
3436 | bool bRet = true; | |||
3437 | if( rFootnote.GetTextFootnote() ) | |||
3438 | { | |||
3439 | sal_uInt16 nWh = rFootnote.IsEndNote() ? sal_uInt16(RES_END_AT_TXTEND) | |||
3440 | : sal_uInt16(RES_FTN_AT_TXTEND); | |||
3441 | const SwSectionNode* pSectNd = rFootnote.GetTextFootnote()->GetTextNode(). | |||
3442 | FindSectionNode(); | |||
3443 | while( pSectNd && FTNEND_ATPGORDOCEND == | |||
3444 | static_cast<const SwFormatFootnoteEndAtTextEnd&>(pSectNd->GetSection().GetFormat()-> | |||
3445 | GetFormatAttr( nWh)).GetValue() ) | |||
3446 | pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode(); | |||
3447 | ||||
3448 | if (!pSectNd) | |||
3449 | bRet = false; // the is ftn/end collected at Page- or Doc-End | |||
3450 | } | |||
3451 | return bRet; | |||
3452 | } | |||
3453 | ||||
3454 | void AttributeOutputBase::TextFootnote( const SwFormatFootnote& rFootnote ) | |||
3455 | { | |||
3456 | sal_uInt16 nTyp; | |||
3457 | if ( rFootnote.IsEndNote() ) | |||
3458 | { | |||
3459 | nTyp = REF_ENDNOTE; | |||
3460 | if ( GetExport().m_bEndAtTextEnd ) | |||
3461 | GetExport().m_bEndAtTextEnd = lcl_IsAtTextEnd( rFootnote ); | |||
3462 | } | |||
3463 | else | |||
3464 | { | |||
3465 | nTyp = REF_FOOTNOTE; | |||
3466 | if ( GetExport().m_bFootnoteAtTextEnd ) | |||
3467 | GetExport().m_bFootnoteAtTextEnd = lcl_IsAtTextEnd( rFootnote ); | |||
3468 | } | |||
3469 | ||||
3470 | // if any reference to this footnote/endnote then insert an internal | |||
3471 | // Bookmark. | |||
3472 | OUString sBkmkNm; | |||
3473 | if ( GetExport().HasRefToFootOrEndnote( rFootnote.IsEndNote(), rFootnote.GetTextFootnote()->GetSeqRefNo())) | |||
3474 | { | |||
3475 | sBkmkNm = MSWordExportBase::GetBookmarkName( nTyp, nullptr, | |||
3476 | rFootnote.GetTextFootnote()->GetSeqRefNo() ); | |||
3477 | GetExport().AppendBookmark( sBkmkNm ); | |||
3478 | } | |||
3479 | ||||
3480 | TextFootnote_Impl( rFootnote ); | |||
3481 | ||||
3482 | if ( !sBkmkNm.isEmpty() ) | |||
3483 | GetExport().AppendBookmark( sBkmkNm ); // FIXME: Why is it added twice? Shouldn't this one go to WW8AttributeOutput::TextFootnote_Impl()? | |||
3484 | } | |||
3485 | ||||
3486 | void WW8AttributeOutput::TextFootnote_Impl( const SwFormatFootnote& rFootnote ) | |||
3487 | { | |||
3488 | WW8_WrPlcFootnoteEdn* pFootnoteEnd; | |||
3489 | if ( rFootnote.IsEndNote() || GetExport().m_rDoc.GetFootnoteInfo().m_ePos == FTNPOS_CHAPTER ) | |||
3490 | pFootnoteEnd = m_rWW8Export.pEdn.get(); | |||
3491 | else | |||
3492 | pFootnoteEnd = m_rWW8Export.pFootnote.get(); | |||
3493 | ||||
3494 | pFootnoteEnd->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), rFootnote ); | |||
3495 | m_rWW8Export.WriteFootnoteBegin( rFootnote, m_rWW8Export.pO.get() ); | |||
3496 | } | |||
3497 | ||||
3498 | void WW8AttributeOutput::TextCharFormat( const SwFormatCharFormat& rCharFormat ) | |||
3499 | { | |||
3500 | if( rCharFormat.GetCharFormat() ) | |||
3501 | { | |||
3502 | m_rWW8Export.InsUInt16( NS_sprm::CIstd::val ); | |||
3503 | ||||
3504 | m_rWW8Export.InsUInt16( m_rWW8Export.GetId( rCharFormat.GetCharFormat() ) ); | |||
3505 | } | |||
3506 | } | |||
3507 | ||||
3508 | /* | |||
3509 | See ww8par6.cxx Read_DoubleLine for some more info | |||
3510 | */ | |||
3511 | void WW8AttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines ) | |||
3512 | { | |||
3513 | // #i28331# - check that bOn is set | |||
3514 | if ( !rTwoLines.GetValue() ) | |||
3515 | return; | |||
3516 | ||||
3517 | m_rWW8Export.InsUInt16( NS_sprm::CFELayout::val ); | |||
3518 | m_rWW8Export.pO->push_back( sal_uInt8(0x06) ); //len 6 | |||
3519 | m_rWW8Export.pO->push_back( sal_uInt8(0x02) ); | |||
3520 | ||||
3521 | sal_Unicode cStart = rTwoLines.GetStartBracket(); | |||
3522 | sal_Unicode cEnd = rTwoLines.GetEndBracket(); | |||
3523 | ||||
3524 | /* | |||
3525 | As per usual we have problems. We can have separate left and right brackets | |||
3526 | in OOo, it doesn't appear that you can in word. Also in word there appear | |||
3527 | to only be a limited number of possibilities, we can use pretty much | |||
3528 | anything. | |||
3529 | ||||
3530 | So if we have none, we export none, if either bracket is set to a known | |||
3531 | word type we export both as that type (with the bracket winning out in | |||
3532 | the case of a conflict simply being the order of test here. | |||
3533 | ||||
3534 | Upshot being a documented created in word will be reexported with no | |||
3535 | ill effects. | |||
3536 | */ | |||
3537 | ||||
3538 | sal_uInt16 nType; | |||
3539 | if (!cStart && !cEnd) | |||
3540 | nType = 0; | |||
3541 | else if ((cStart == '{') || (cEnd == '}')) | |||
3542 | nType = 4; | |||
3543 | else if ((cStart == '<') || (cEnd == '>')) | |||
3544 | nType = 3; | |||
3545 | else if ((cStart == '[') || (cEnd == ']')) | |||
3546 | nType = 2; | |||
3547 | else | |||
3548 | nType = 1; | |||
3549 | m_rWW8Export.InsUInt16( nType ); | |||
3550 | static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 }; | |||
3551 | m_rWW8Export.pO->insert( m_rWW8Export.pO->end(), aZeroArr, aZeroArr+3); | |||
3552 | } | |||
3553 | ||||
3554 | void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule ) | |||
3555 | { | |||
3556 | const SwTextNode* pTextNd = nullptr; | |||
3557 | if (rNumRule.GetValue().isEmpty()) | |||
3558 | { | |||
3559 | ParaNumRule_Impl(pTextNd, 0, 0); | |||
3560 | return; | |||
3561 | } | |||
3562 | const SwNumRule* pRule = GetExport().m_rDoc.FindNumRulePtr( | |||
3563 | rNumRule.GetValue() ); | |||
3564 | if (!pRule) | |||
3565 | return; | |||
3566 | ||||
3567 | sal_uInt16 nNumId = GetExport().GetNumberingId(*pRule) + 1; | |||
3568 | sal_uInt8 nLvl = 0; | |||
3569 | ||||
3570 | if (!GetExport().m_pOutFormatNode) | |||
3571 | { | |||
3572 | ParaNumRule_Impl(pTextNd, nLvl, nNumId); | |||
3573 | return; | |||
3574 | } | |||
3575 | ||||
3576 | if ( dynamic_cast< const SwContentNode *>( GetExport().m_pOutFormatNode ) != nullptr ) | |||
3577 | { | |||
3578 | pTextNd = static_cast<const SwTextNode*>(GetExport().m_pOutFormatNode); | |||
3579 | ||||
3580 | if( pTextNd->IsCountedInList()) | |||
3581 | { | |||
3582 | int nLevel = pTextNd->GetActualListLevel(); | |||
3583 | ||||
3584 | if (nLevel < 0) | |||
3585 | nLevel = 0; | |||
3586 | ||||
3587 | if (nLevel >= MAXLEVEL) | |||
3588 | nLevel = MAXLEVEL - 1; | |||
3589 | ||||
3590 | nLvl = static_cast< sal_uInt8 >(nLevel); | |||
3591 | ||||
3592 | if (GetExport().GetExportFormat() == MSWordExportBase::DOCX) // FIXME | |||
3593 | { | |||
3594 | // tdf#95848 find the abstract list definition | |||
3595 | OUString const listId(pTextNd->GetListId()); | |||
3596 | if (!listId.isEmpty() | |||
3597 | && (listId != pRule->GetDefaultListId() // default list id uses the 1:1 mapping | |||
3598 | || pTextNd->IsListRestart()) // or restarting previous list | |||
3599 | ) | |||
3600 | { | |||
3601 | SwList const*const pList( | |||
3602 | GetExport().m_rDoc.getIDocumentListsAccess().getListByName(listId)); | |||
3603 | if (pList) | |||
3604 | { | |||
3605 | SwNumRule const*const pAbstractRule( | |||
3606 | GetExport().m_rDoc.FindNumRulePtr( | |||
3607 | pList->GetDefaultListStyleName())); | |||
3608 | assert(pAbstractRule)(static_cast <bool> (pAbstractRule) ? void (0) : __assert_fail ("pAbstractRule", "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 3608, __extension__ __PRETTY_FUNCTION__)); | |||
3609 | if (pAbstractRule == pRule && !pTextNd->IsListRestart()) | |||
3610 | { | |||
3611 | // different list, but no override | |||
3612 | nNumId = GetExport().DuplicateAbsNum(listId, *pAbstractRule) + 1; | |||
3613 | } | |||
3614 | else | |||
3615 | { | |||
3616 | nNumId = GetExport().OverrideNumRule( | |||
3617 | *pRule, listId, *pAbstractRule) + 1; | |||
3618 | ||||
3619 | if (pTextNd->IsListRestart()) | |||
3620 | { | |||
3621 | // For restarted lists we should also keep value for | |||
3622 | // future w:lvlOverride / w:startOverride | |||
3623 | GetExport().AddListLevelOverride(nNumId-1, pTextNd->GetActualListLevel(), | |||
3624 | pTextNd->GetActualListStartValue()); | |||
3625 | } | |||
3626 | } | |||
3627 | } | |||
3628 | } | |||
3629 | } | |||
3630 | } | |||
3631 | else | |||
3632 | { | |||
3633 | // #i44815# adjust numbering for numbered paragraphs | |||
3634 | // without number (NO_NUMLEVEL). These paragraphs | |||
3635 | // will receive a list id 0, which WW interprets as | |||
3636 | // 'no number'. | |||
3637 | nNumId = 0; | |||
3638 | } | |||
3639 | } | |||
3640 | else if ( dynamic_cast< const SwTextFormatColl *>( GetExport().m_pOutFormatNode ) != nullptr ) | |||
3641 | { | |||
3642 | const SwTextFormatColl* pC = static_cast<const SwTextFormatColl*>(GetExport().m_pOutFormatNode); | |||
3643 | if ( pC && pC->IsAssignedToListLevelOfOutlineStyle() ) | |||
3644 | nLvl = static_cast< sal_uInt8 >( pC->GetAssignedOutlineStyleLevel() ); | |||
3645 | } | |||
3646 | ||||
3647 | if ( nLvl >= WW8ListManager::nMaxLevel ) | |||
3648 | nLvl = WW8ListManager::nMaxLevel - 1; | |||
3649 | ||||
3650 | ParaNumRule_Impl( pTextNd, nLvl, nNumId); | |||
3651 | } | |||
3652 | ||||
3653 | void WW8AttributeOutput::ParaNumRule_Impl(const SwTextNode* /*pTextNd*/, | |||
3654 | sal_Int32 const nLvl, sal_Int32 const nNumId) | |||
3655 | { | |||
3656 | if (USHRT_MAX(32767 *2 +1) == nNumId) | |||
3657 | return; | |||
3658 | ||||
3659 | // write sprmPIlvl and sprmPIlfo | |||
3660 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::PIlvl::val ); | |||
3661 | m_rWW8Export.pO->push_back( ::sal::static_int_cast<sal_uInt8>(nLvl) ); | |||
3662 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::PIlfo::val ); | |||
3663 | SwWW8Writer::InsUInt16( *m_rWW8Export.pO, ::sal::static_int_cast<sal_uInt16>(nNumId) ); | |||
3664 | } | |||
3665 | ||||
3666 | /* File FRMATR.HXX */ | |||
3667 | ||||
3668 | void WW8AttributeOutput::FormatFrameSize( const SwFormatFrameSize& rSize ) | |||
3669 | { | |||
3670 | if( m_rWW8Export.m_bOutFlyFrameAttrs ) // Flys | |||
3671 | { | |||
3672 | if( m_rWW8Export.m_bOutGrf ) | |||
3673 | return; // Fly around graphic -> Auto-size | |||
3674 | ||||
3675 | //???? What about percentages ??? | |||
3676 | if ( rSize.GetWidth() && rSize.GetWidthSizeType() == SwFrameSize::Fixed) | |||
3677 | { | |||
3678 | //"sprmPDxaWidth" | |||
3679 | m_rWW8Export.InsUInt16( NS_sprm::PDxaWidth::val ); | |||
3680 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(rSize.GetWidth()) ); | |||
3681 | } | |||
3682 | ||||
3683 | if ( rSize.GetHeight() ) | |||
3684 | { | |||
3685 | // sprmPWHeightAbs | |||
3686 | m_rWW8Export.InsUInt16( NS_sprm::PWHeightAbs::val ); | |||
3687 | ||||
3688 | sal_uInt16 nH = 0; | |||
3689 | switch ( rSize.GetHeightSizeType() ) | |||
3690 | { | |||
3691 | case SwFrameSize::Variable: break; | |||
3692 | case SwFrameSize::Fixed: nH = static_cast<sal_uInt16>(rSize.GetHeight()) & 0x7fff; break; | |||
3693 | default: nH = static_cast<sal_uInt16>(rSize.GetHeight()) | 0x8000; break; | |||
3694 | } | |||
3695 | m_rWW8Export.InsUInt16( nH ); | |||
3696 | } | |||
3697 | } | |||
3698 | else if( m_rWW8Export.m_bOutPageDescs ) // PageDesc : width + height | |||
3699 | { | |||
3700 | if( m_rWW8Export.m_pCurrentPageDesc->GetLandscape() ) | |||
3701 | { | |||
3702 | /*sprmSBOrientation*/ | |||
3703 | m_rWW8Export.InsUInt16( NS_sprm::SBOrientation::val ); | |||
3704 | m_rWW8Export.pO->push_back( 2 ); | |||
3705 | } | |||
3706 | ||||
3707 | /*sprmSXaPage*/ | |||
3708 | m_rWW8Export.InsUInt16( NS_sprm::SXaPage::val ); | |||
3709 | m_rWW8Export.InsUInt16( | |||
3710 | msword_cast<sal_uInt16>(SvxPaperInfo::GetSloppyPaperDimension(rSize.GetWidth()))); | |||
3711 | ||||
3712 | /*sprmSYaPage*/ | |||
3713 | m_rWW8Export.InsUInt16( NS_sprm::SYaPage::val ); | |||
3714 | m_rWW8Export.InsUInt16( | |||
3715 | msword_cast<sal_uInt16>(SvxPaperInfo::GetSloppyPaperDimension(rSize.GetHeight()))); | |||
3716 | } | |||
3717 | } | |||
3718 | ||||
3719 | // FillOrder is still missing | |||
3720 | ||||
3721 | /** | |||
3722 | * ReplaceCr() is used for Pagebreaks and Pagedescs. An already written CR | |||
3723 | * will be replaced by a break character. Replace must be called right after | |||
3724 | * the writing of CR. | |||
3725 | * | |||
3726 | * @return FilePos + 1 of the replaced CR or 0 if nothing was replaced. | |||
3727 | */ | |||
3728 | sal_uLong WW8Export::ReplaceCr( sal_uInt8 nChar ) | |||
3729 | { | |||
3730 | OSL_ENSURE( nChar, "replaced with 0 crashes WW97/95" )do { if (true && (!(nChar))) { sal_detail_logFormat(( SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "3730" ": "), "%s", "replaced with 0 crashes WW97/95"); } } while (false); | |||
3731 | ||||
3732 | bool bReplaced = false; | |||
3733 | SvStream& rStrm = Strm(); | |||
3734 | sal_uLong nRetPos = 0, nPos = rStrm.Tell(); | |||
3735 | //If there is at least two characters already output | |||
3736 | if (nPos - 2 >= o3tl::make_unsigned(pFib->m_fcMin)) | |||
3737 | { | |||
3738 | sal_uInt16 nUCode=0; | |||
3739 | ||||
3740 | rStrm.SeekRel(-2); | |||
3741 | rStrm.ReadUInt16( nUCode ); | |||
3742 | //If the last char was a cr | |||
3743 | if (nUCode == 0x0d) // CR ? | |||
3744 | { | |||
3745 | if ((nChar == 0x0c) && | |||
3746 | (nPos - 4 >= o3tl::make_unsigned(pFib->m_fcMin))) | |||
3747 | { | |||
3748 | rStrm.SeekRel(-4); | |||
3749 | rStrm.ReadUInt16( nUCode ); | |||
3750 | } | |||
3751 | else | |||
3752 | { | |||
3753 | rStrm.SeekRel(-2); | |||
3754 | nUCode = 0x0; | |||
3755 | } | |||
3756 | //And the para is not of len 0, then replace this cr with the mark | |||
3757 | //#120140# If there is a cr before a column break, need replace the cr. So remove the "nChar==0x0e" check. | |||
3758 | if( nUCode == 0x0d ) | |||
3759 | bReplaced = false; | |||
3760 | else | |||
3761 | { | |||
3762 | bReplaced = true; | |||
3763 | WriteChar(nChar); | |||
3764 | nRetPos = nPos; | |||
3765 | } | |||
3766 | } | |||
3767 | else if ((nUCode == 0x0c) && (nChar == 0x0e)) | |||
3768 | { | |||
3769 | // a column break after a section has no effect in writer | |||
3770 | bReplaced = true; | |||
3771 | } | |||
3772 | rStrm.Seek( nPos ); | |||
3773 | } | |||
3774 | else | |||
3775 | bReplaced = true; | |||
3776 | ||||
3777 | if (!bReplaced) | |||
3778 | { | |||
3779 | // then write as normal char | |||
3780 | WriteChar(nChar); | |||
3781 | m_pPiece->SetParaBreak(); | |||
3782 | m_pPapPlc->AppendFkpEntry(rStrm.Tell()); | |||
3783 | m_pChpPlc->AppendFkpEntry(rStrm.Tell()); | |||
3784 | nRetPos = rStrm.Tell(); | |||
3785 | } | |||
3786 | return nRetPos; | |||
3787 | } | |||
3788 | ||||
3789 | void WW8AttributeOutput::TableRowEnd(sal_uInt32 nDepth) | |||
3790 | { | |||
3791 | if ( nDepth == 1 ) | |||
3792 | m_rWW8Export.WriteChar( 0x07 ); | |||
3793 | else if ( nDepth > 1 ) | |||
3794 | m_rWW8Export.WriteChar( 0x0d ); | |||
3795 | ||||
3796 | //Technically in a word document this is a different value for a row ends | |||
3797 | //that are not row ends directly after a cell with a graphic. But it | |||
3798 | //doesn't seem to make a difference | |||
3799 | //pMagicTable->Append(Fc2Cp(Strm().Tell()),0x1B6); | |||
3800 | } | |||
3801 | ||||
3802 | void AttributeOutputBase::FormatPageDescription( const SwFormatPageDesc& rPageDesc ) | |||
3803 | { | |||
3804 | if ( GetExport().m_bStyDef && dynamic_cast< const SwTextFormatColl *>( GetExport().m_pOutFormatNode ) ) | |||
3805 | { | |||
3806 | const SwTextFormatColl* pC = static_cast<const SwTextFormatColl*>(GetExport().m_pOutFormatNode); | |||
3807 | if ( (SfxItemState::SET != pC->GetItemState( RES_BREAK, false ) ) && rPageDesc.KnowsPageDesc() ) | |||
3808 | FormatBreak( SvxFormatBreakItem( SvxBreak::PageBefore, RES_BREAK ) ); | |||
3809 | } | |||
3810 | } | |||
3811 | ||||
3812 | void WW8AttributeOutput::PageBreakBefore( bool bBreak ) | |||
3813 | { | |||
3814 | // sprmPPageBreakBefore/sprmPFPageBreakBefore | |||
3815 | m_rWW8Export.InsUInt16( NS_sprm::PFPageBreakBefore::val ); | |||
3816 | ||||
3817 | m_rWW8Export.pO->push_back( bBreak ? 1 : 0 ); | |||
3818 | } | |||
3819 | ||||
3820 | /** | |||
3821 | * breaks write nothing in the output field rWrt.pO, | |||
3822 | * but only in the text stream (requirement so they can | |||
3823 | * be called from Out_Break...) | |||
3824 | */ | |||
3825 | void AttributeOutputBase::FormatBreak( const SvxFormatBreakItem& rBreak ) | |||
3826 | { | |||
3827 | if ( GetExport().m_bStyDef ) | |||
3828 | { | |||
3829 | switch ( rBreak.GetBreak() ) | |||
3830 | { | |||
3831 | case SvxBreak::NONE: | |||
3832 | case SvxBreak::PageBefore: | |||
3833 | case SvxBreak::PageBoth: | |||
3834 | PageBreakBefore( rBreak.GetValue() != SvxBreak::NONE ); | |||
3835 | break; | |||
3836 | default: | |||
3837 | break; | |||
3838 | } | |||
3839 | } | |||
3840 | else if ( !GetExport().m_pParentFrame ) | |||
3841 | { | |||
3842 | sal_uInt8 nC = 0; | |||
3843 | bool bBefore = false; | |||
3844 | // #i76300# - Note: Can only be <true>, if <bBefore> equals <false>. | |||
3845 | bool bCheckForFollowPageDesc = false; | |||
3846 | ||||
3847 | switch ( rBreak.GetBreak() ) | |||
3848 | { | |||
3849 | case SvxBreak::NONE: // disabled | |||
3850 | if ( !GetExport().m_bBreakBefore ) | |||
3851 | PageBreakBefore( false ); | |||
3852 | return; | |||
3853 | ||||
3854 | case SvxBreak::ColumnBefore: // ColumnBreak | |||
3855 | bBefore = true; | |||
3856 | [[fallthrough]]; | |||
3857 | case SvxBreak::ColumnAfter: | |||
3858 | case SvxBreak::ColumnBoth: | |||
3859 | if ( GetExport().m_rDoc.getIDocumentSettingAccess().get( DocumentSettingId::TREAT_SINGLE_COLUMN_BREAK_AS_PAGE_BREAK ) | |||
3860 | || GetExport().Sections().CurrentNumberOfColumns( GetExport().m_rDoc ) > 1 ) | |||
3861 | { | |||
3862 | nC = msword::ColumnBreak; | |||
3863 | } | |||
3864 | break; | |||
3865 | ||||
3866 | case SvxBreak::PageBefore: // PageBreak | |||
3867 | // From now on(fix for #i77900#) we prefer to save a page break | |||
3868 | // as paragraph attribute (if the exporter is OK with that), | |||
3869 | // this has to be done after the export of the paragraph ( => | |||
3870 | // !GetExport().bBreakBefore ) | |||
3871 | if (GetExport().PreferPageBreakBefore()) | |||
3872 | { | |||
3873 | if (!GetExport().m_bBreakBefore) | |||
3874 | PageBreakBefore(true); | |||
3875 | } | |||
3876 | else | |||
3877 | { | |||
3878 | bBefore = true; | |||
3879 | nC = msword::PageBreak; | |||
3880 | } | |||
3881 | break; | |||
3882 | case SvxBreak::PageAfter: | |||
3883 | case SvxBreak::PageBoth: | |||
3884 | nC = msword::PageBreak; | |||
3885 | // #i76300# - check for follow page description, | |||
3886 | // if current writing attributes of a paragraph. | |||
3887 | if ( dynamic_cast< const SwTextNode* >( GetExport().m_pOutFormatNode ) && | |||
3888 | GetExport().GetCurItemSet() ) | |||
3889 | { | |||
3890 | bCheckForFollowPageDesc = true; | |||
3891 | } | |||
3892 | break; | |||
3893 | ||||
3894 | default: | |||
3895 | break; | |||
3896 | } | |||
3897 | ||||
3898 | if ( ( bBefore == GetExport().m_bBreakBefore ) && nC ) | |||
3899 | { | |||
3900 | // #i76300# | |||
3901 | bool bFollowPageDescWritten = false; | |||
3902 | if ( bCheckForFollowPageDesc ) | |||
3903 | { | |||
3904 | bFollowPageDescWritten = | |||
3905 | GetExport().OutputFollowPageDesc( GetExport().GetCurItemSet(), | |||
3906 | dynamic_cast<const SwTextNode*>( GetExport().m_pOutFormatNode ) ); | |||
3907 | } | |||
3908 | if ( !bFollowPageDescWritten ) | |||
3909 | { | |||
3910 | SectionBreak(nC, !bBefore); | |||
3911 | } | |||
3912 | } | |||
3913 | } | |||
3914 | } | |||
3915 | ||||
3916 | void WW8AttributeOutput::SectionBreak( sal_uInt8 nC, bool /*bBreakAfter*/, const WW8_SepInfo* /*pSectionInfo*/ ) | |||
3917 | { | |||
3918 | m_rWW8Export.ReplaceCr( nC ); | |||
3919 | } | |||
3920 | ||||
3921 | sal_uInt32 AttributeOutputBase::GridCharacterPitch( const SwTextGridItem& rGrid ) const | |||
3922 | { | |||
3923 | MSWordStyles * pStyles = GetExport().m_pStyles.get(); | |||
3924 | const SwFormat * pSwFormat = pStyles->GetSwFormat(0); | |||
3925 | ||||
3926 | sal_uInt32 nPageCharSize = 0; | |||
3927 | ||||
3928 | if (pSwFormat != nullptr) | |||
3929 | { | |||
3930 | nPageCharSize = ItemGet<SvxFontHeightItem> | |||
3931 | (*pSwFormat, RES_CHRATR_FONTSIZE).GetHeight(); | |||
3932 | } | |||
3933 | sal_uInt16 nPitch = rGrid.IsSquaredMode() ? rGrid.GetBaseHeight() : | |||
3934 | rGrid.GetBaseWidth( ); | |||
3935 | ||||
3936 | sal_Int32 nCharWidth = nPitch - nPageCharSize; | |||
3937 | sal_Int32 nFraction = nCharWidth % 20; | |||
3938 | if ( nCharWidth < 0 ) | |||
3939 | nFraction = 20 + nFraction; | |||
3940 | nFraction = ( nFraction * 0xFFF ) / 20; | |||
3941 | nFraction = ( nFraction & 0x00000FFF ); | |||
3942 | ||||
3943 | sal_Int32 nMain = nCharWidth / 20; | |||
3944 | if ( nCharWidth < 0 ) | |||
3945 | nMain -= 1; | |||
3946 | nMain = nMain * 0x1000; | |||
3947 | nMain = ( nMain & 0xFFFFF000 ); | |||
3948 | ||||
3949 | return sal_uInt32( nFraction + nMain ); | |||
3950 | } | |||
3951 | ||||
3952 | void WW8AttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid ) | |||
3953 | { | |||
3954 | if (!m_rWW8Export.m_bOutPageDescs) | |||
3955 | return; | |||
3956 | ||||
3957 | sal_uInt16 nGridType = 0; | |||
3958 | switch ( rGrid.GetGridType() ) | |||
3959 | { | |||
3960 | default: | |||
3961 | OSL_FAIL("Unknown grid type")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "3961" ": "), "%s", "Unknown grid type"); } } while (false ); | |||
3962 | [[fallthrough]]; | |||
3963 | case GRID_NONE: | |||
3964 | nGridType = 0; | |||
3965 | break; | |||
3966 | case GRID_LINES_ONLY: | |||
3967 | nGridType = 2; | |||
3968 | break; | |||
3969 | case GRID_LINES_CHARS: | |||
3970 | if ( rGrid.IsSnapToChars() ) | |||
3971 | nGridType = 3; | |||
3972 | else | |||
3973 | nGridType = 1; | |||
3974 | break; | |||
3975 | } | |||
3976 | m_rWW8Export.InsUInt16( NS_sprm::SClm::val ); | |||
3977 | m_rWW8Export.InsUInt16( nGridType ); | |||
3978 | ||||
3979 | sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight(); | |||
3980 | m_rWW8Export.InsUInt16( NS_sprm::SDyaLinePitch::val ); | |||
3981 | m_rWW8Export.InsUInt16( nHeight ); | |||
3982 | ||||
3983 | m_rWW8Export.InsUInt16( NS_sprm::SDxtCharSpace::val ); | |||
3984 | m_rWW8Export.InsUInt32( GridCharacterPitch( rGrid ) ); | |||
3985 | } | |||
3986 | ||||
3987 | void WW8AttributeOutput::FormatPaperBin( const SvxPaperBinItem& rPaperBin ) | |||
3988 | { | |||
3989 | if ( !m_rWW8Export.m_bOutPageDescs ) | |||
3990 | return; | |||
3991 | ||||
3992 | sal_uInt16 nVal; | |||
3993 | switch ( rPaperBin.GetValue() ) | |||
3994 | { | |||
3995 | case 0: nVal = 15; break; // Automatically select | |||
3996 | case 1: nVal = 1; break; // Upper paper tray | |||
3997 | case 2: nVal = 4; break; // Manual paper feed | |||
3998 | default: nVal = 0; break; | |||
3999 | } | |||
4000 | ||||
4001 | if ( nVal ) | |||
4002 | { | |||
4003 | m_rWW8Export.InsUInt16( m_rWW8Export.m_bOutFirstPage | |||
4004 | ? NS_sprm::SDmBinFirst::val : NS_sprm::SDmBinOther::val ); | |||
4005 | ||||
4006 | m_rWW8Export.InsUInt16( nVal ); | |||
4007 | } | |||
4008 | } | |||
4009 | ||||
4010 | void WW8AttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLR ) | |||
4011 | { | |||
4012 | // Flys are still missing ( see RTF ) | |||
4013 | ||||
4014 | if ( m_rWW8Export.m_bOutFlyFrameAttrs ) // Flys | |||
4015 | { | |||
4016 | // sprmPDxaFromText10 | |||
4017 | m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText10 ); | |||
4018 | // use average, since WW only knows one value | |||
4019 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>( ( rLR.GetLeft() + rLR.GetRight() ) / 2 ) ); | |||
4020 | } | |||
4021 | else if ( m_rWW8Export.m_bOutPageDescs ) // PageDescs | |||
4022 | { | |||
4023 | m_pageMargins.nLeft = 0; | |||
4024 | m_pageMargins.nRight = 0; | |||
4025 | ||||
4026 | if ( auto pBoxItem = static_cast<const SvxBoxItem*>(m_rWW8Export.HasItem( RES_BOX )) ) | |||
4027 | { | |||
4028 | m_pageMargins.nLeft = pBoxItem->CalcLineSpace( SvxBoxItemLine::LEFT, /*bEvenIfNoLine*/true ); | |||
4029 | m_pageMargins.nRight = pBoxItem->CalcLineSpace( SvxBoxItemLine::RIGHT, /*bEvenIfNoLine*/true ); | |||
4030 | } | |||
4031 | ||||
4032 | m_pageMargins.nLeft += sal::static_int_cast<sal_uInt16>(rLR.GetLeft()); | |||
4033 | m_pageMargins.nRight += sal::static_int_cast<sal_uInt16>(rLR.GetRight()); | |||
4034 | ||||
4035 | // sprmSDxaLeft | |||
4036 | m_rWW8Export.InsUInt16( NS_sprm::SDxaLeft::val ); | |||
4037 | m_rWW8Export.InsUInt16( m_pageMargins.nLeft ); | |||
4038 | ||||
4039 | // sprmSDxaRight | |||
4040 | m_rWW8Export.InsUInt16( NS_sprm::SDxaRight::val ); | |||
4041 | m_rWW8Export.InsUInt16( m_pageMargins.nRight ); | |||
4042 | } | |||
4043 | else | |||
4044 | { // normal paragraphs | |||
4045 | // sprmPDxaLeft | |||
4046 | m_rWW8Export.InsUInt16( 0x845E ); //asian version ? | |||
4047 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(rLR.GetTextLeft()) ); | |||
4048 | ||||
4049 | // sprmPDxaRight | |||
4050 | m_rWW8Export.InsUInt16( 0x845D ); //asian version ? | |||
4051 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>(rLR.GetRight()) ); | |||
4052 | ||||
4053 | // sprmPDxaLeft1 | |||
4054 | m_rWW8Export.InsUInt16( 0x8460 ); //asian version ? | |||
4055 | m_rWW8Export.InsUInt16( rLR.GetTextFirstLineOffset() ); | |||
4056 | } | |||
4057 | } | |||
4058 | ||||
4059 | void WW8AttributeOutput::FormatULSpace( const SvxULSpaceItem& rUL ) | |||
4060 | { | |||
4061 | // Flys are still missing ( see RTF ) | |||
4062 | ||||
4063 | if ( m_rWW8Export.m_bOutFlyFrameAttrs ) // Flys | |||
4064 | { | |||
4065 | // sprmPDyaFromText | |||
4066 | m_rWW8Export.InsUInt16( NS_sprm::PDyaFromText::val ); | |||
4067 | // use average, since WW only knows one value | |||
4068 | m_rWW8Export.InsUInt16( static_cast<sal_uInt16>( ( rUL.GetUpper() + rUL.GetLower() ) / 2 ) ); | |||
4069 | } | |||
4070 | else if ( m_rWW8Export.m_bOutPageDescs ) // Page-UL | |||
4071 | { | |||
4072 | OSL_ENSURE( m_rWW8Export.GetCurItemSet(), "Impossible" )do { if (true && (!(m_rWW8Export.GetCurItemSet()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl" ), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4072" ": "), "%s", "Impossible"); } } while (false); | |||
4073 | if ( !m_rWW8Export.GetCurItemSet() ) | |||
4074 | return; | |||
4075 | ||||
4076 | HdFtDistanceGlue aDistances( *m_rWW8Export.GetCurItemSet() ); | |||
4077 | ||||
4078 | if ( aDistances.HasHeader() ) | |||
4079 | { | |||
4080 | //sprmSDyaHdrTop | |||
4081 | m_rWW8Export.InsUInt16( NS_sprm::SDyaHdrTop::val ); | |||
4082 | m_rWW8Export.InsUInt16( aDistances.dyaHdrTop ); | |||
4083 | } | |||
4084 | ||||
4085 | // sprmSDyaTop | |||
4086 | m_rWW8Export.InsUInt16( NS_sprm::SDyaTop::val ); | |||
4087 | m_rWW8Export.InsUInt16( aDistances.dyaTop ); | |||
4088 | m_pageMargins.nTop = aDistances.dyaTop; | |||
4089 | ||||
4090 | if ( aDistances.HasFooter() ) | |||
4091 | { | |||
4092 | //sprmSDyaHdrBottom | |||
4093 | m_rWW8Export.InsUInt16( NS_sprm::SDyaHdrBottom::val ); | |||
4094 | m_rWW8Export.InsUInt16( aDistances.dyaHdrBottom ); | |||
4095 | } | |||
4096 | ||||
4097 | //sprmSDyaBottom | |||
4098 | m_rWW8Export.InsUInt16( NS_sprm::SDyaBottom::val ); | |||
4099 | m_rWW8Export.InsUInt16( aDistances.dyaBottom ); | |||
4100 | m_pageMargins.nBottom = aDistances.dyaBottom; | |||
4101 | } | |||
4102 | else | |||
4103 | { | |||
4104 | // sprmPDyaBefore | |||
4105 | m_rWW8Export.InsUInt16( NS_sprm::PDyaBefore::val ); | |||
4106 | m_rWW8Export.InsUInt16( rUL.GetUpper() ); | |||
4107 | // sprmPDyaAfter | |||
4108 | m_rWW8Export.InsUInt16( NS_sprm::PDyaAfter::val ); | |||
4109 | m_rWW8Export.InsUInt16( rUL.GetLower() ); | |||
4110 | // sprmPFContextualSpacing | |||
4111 | if (rUL.GetContext()) | |||
4112 | { | |||
4113 | m_rWW8Export.InsUInt16(NS_sprm::PFContextualSpacing::val); | |||
4114 | m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(rUL.GetContext()) ); | |||
4115 | } | |||
4116 | } | |||
4117 | } | |||
4118 | ||||
4119 | // print, opaque, protect are still missing | |||
4120 | ||||
4121 | void WW8AttributeOutput::FormatSurround( const SwFormatSurround& rSurround ) | |||
4122 | { | |||
4123 | if ( m_rWW8Export.m_bOutFlyFrameAttrs ) | |||
4124 | { | |||
4125 | m_rWW8Export.InsUInt16( NS_sprm::PWr::val ); | |||
4126 | ||||
4127 | m_rWW8Export.pO->push_back( | |||
4128 | ( css::text::WrapTextMode_NONE != rSurround.GetSurround() ) ? 2 : 1 ); | |||
4129 | } | |||
4130 | } | |||
4131 | ||||
4132 | void WW8AttributeOutput::FormatVertOrientation( const SwFormatVertOrient& rFlyVert ) | |||
4133 | { | |||
4134 | ||||
4135 | //!!!! anchor type and corresponding borders are still missing | |||
4136 | if ( !m_rWW8Export.m_bOutFlyFrameAttrs ) | |||
4137 | return; | |||
4138 | ||||
4139 | short nPos; | |||
4140 | switch( rFlyVert.GetVertOrient() ) | |||
4141 | { | |||
4142 | case text::VertOrientation::NONE: | |||
4143 | nPos = static_cast<short>(rFlyVert.GetPos()); | |||
4144 | break; | |||
4145 | case text::VertOrientation::CENTER: | |||
4146 | case text::VertOrientation::LINE_CENTER: | |||
4147 | nPos = -8; | |||
4148 | break; | |||
4149 | case text::VertOrientation::BOTTOM: | |||
4150 | case text::VertOrientation::LINE_BOTTOM: | |||
4151 | nPos = -12; | |||
4152 | break; | |||
4153 | case text::VertOrientation::TOP: | |||
4154 | case text::VertOrientation::LINE_TOP: | |||
4155 | default: | |||
4156 | nPos = -4; | |||
4157 | break; | |||
4158 | } | |||
4159 | ||||
4160 | // sprmPDyaAbs | |||
4161 | m_rWW8Export.InsUInt16( NS_sprm::PDyaAbs::val ); | |||
4162 | m_rWW8Export.InsUInt16( nPos ); | |||
4163 | } | |||
4164 | ||||
4165 | void WW8AttributeOutput::FormatHorizOrientation( const SwFormatHoriOrient& rFlyHori ) | |||
4166 | { | |||
4167 | if ( !m_rWW8Export.m_pParentFrame ) | |||
4168 | { | |||
4169 | OSL_ENSURE( m_rWW8Export.m_pParentFrame, "HoriOrient without mpParentFrame !!" )do { if (true && (!(m_rWW8Export.m_pParentFrame))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4169" ": "), "%s", "HoriOrient without mpParentFrame !!" ); } } while (false); | |||
4170 | return; | |||
4171 | } | |||
4172 | ||||
4173 | //!!!! anchor type and corresponding borders are still missing | |||
4174 | if ( !m_rWW8Export.m_bOutFlyFrameAttrs ) | |||
4175 | return; | |||
4176 | ||||
4177 | short nPos; | |||
4178 | switch( rFlyHori.GetHoriOrient() ) | |||
4179 | { | |||
4180 | case text::HoriOrientation::NONE: | |||
4181 | nPos = static_cast<short>(rFlyHori.GetPos()); | |||
4182 | if( !nPos ) | |||
4183 | nPos = 1; // WW: 0 is reserved | |||
4184 | break; | |||
4185 | case text::HoriOrientation::LEFT: | |||
4186 | nPos = rFlyHori.IsPosToggle() ? -12 : 0; | |||
4187 | break; | |||
4188 | case text::HoriOrientation::RIGHT: | |||
4189 | nPos = rFlyHori.IsPosToggle() ? -16 : -8; | |||
4190 | break; | |||
4191 | case text::HoriOrientation::CENTER: | |||
4192 | case text::HoriOrientation::FULL: // FULL only for tables | |||
4193 | default: | |||
4194 | nPos = -4; | |||
4195 | break; | |||
4196 | } | |||
4197 | ||||
4198 | // sprmPDxaAbs | |||
4199 | m_rWW8Export.InsUInt16( NS_sprm::PDxaAbs::val ); | |||
4200 | m_rWW8Export.InsUInt16( nPos ); | |||
4201 | } | |||
4202 | ||||
4203 | void WW8AttributeOutput::FormatAnchor( const SwFormatAnchor& rAnchor ) | |||
4204 | { | |||
4205 | OSL_ENSURE( m_rWW8Export.m_pParentFrame, "Anchor without mpParentFrame !!" )do { if (true && (!(m_rWW8Export.m_pParentFrame))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4205" ": "), "%s", "Anchor without mpParentFrame !!"); } } while (false); | |||
4206 | ||||
4207 | if ( !m_rWW8Export.m_bOutFlyFrameAttrs ) | |||
4208 | return; | |||
4209 | ||||
4210 | sal_uInt8 nP = 0; | |||
4211 | switch ( rAnchor.GetAnchorId() ) | |||
4212 | { | |||
4213 | case RndStdIds::FLY_AT_PAGE: | |||
4214 | // vertical: page | horizontal: page | |||
4215 | nP |= (1 << 4) | (2 << 6); | |||
4216 | break; | |||
4217 | // in case of Fly as characters: set paragraph-bound!!! | |||
4218 | case RndStdIds::FLY_AT_FLY: | |||
4219 | case RndStdIds::FLY_AT_CHAR: | |||
4220 | case RndStdIds::FLY_AT_PARA: | |||
4221 | case RndStdIds::FLY_AS_CHAR: | |||
4222 | // vertical: page | horizontal: page | |||
4223 | nP |= (2 << 4) | (0 << 6); | |||
4224 | break; | |||
4225 | default: | |||
4226 | break; | |||
4227 | } | |||
4228 | ||||
4229 | // sprmPPc | |||
4230 | m_rWW8Export.InsUInt16( NS_sprm::PPc::val ); | |||
4231 | m_rWW8Export.pO->push_back( nP ); | |||
4232 | } | |||
4233 | ||||
4234 | void WW8AttributeOutput::FormatBackground( const SvxBrushItem& rBrush ) | |||
4235 | { | |||
4236 | // WW cannot have background in a section | |||
4237 | if ( m_rWW8Export.m_bOutPageDescs ) | |||
4238 | return; | |||
4239 | ||||
4240 | WW8_SHD aSHD; | |||
4241 | WW8Export::TransBrush( rBrush.GetColor(), aSHD ); | |||
4242 | ||||
4243 | m_rWW8Export.InsUInt16( NS_sprm::PShd80::val ); | |||
4244 | m_rWW8Export.InsUInt16( aSHD.GetValue() ); | |||
4245 | ||||
4246 | m_rWW8Export.InsUInt16( NS_sprm::PShd::val ); | |||
4247 | m_rWW8Export.pO->push_back( 10 ); //size of operand: MUST be 10 | |||
4248 | m_rWW8Export.InsUInt32( 0xFF000000 ); //cvFore: Foreground BGR = cvAuto | |||
4249 | m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor() ) ); //cvBack | |||
4250 | m_rWW8Export.InsUInt16( 0x0000 ); //iPat: specifies the pattern used for shading = clear/100% background | |||
4251 | } | |||
4252 | ||||
4253 | void WW8AttributeOutput::FormatFillStyle( const XFillStyleItem& rFillStyle ) | |||
4254 | { | |||
4255 | // WW cannot have background in a section | |||
4256 | if ( m_rWW8Export.m_bOutPageDescs ) | |||
4257 | return; | |||
4258 | ||||
4259 | // see MSWordExportBase::OutputItemSet for how _SOLID is handled | |||
4260 | if ( rFillStyle.GetValue() != drawing::FillStyle_NONE ) | |||
4261 | return; | |||
4262 | ||||
4263 | //Shd80Nil | |||
4264 | m_rWW8Export.InsUInt16( NS_sprm::PShd80::val ); | |||
4265 | m_rWW8Export.InsUInt16( 0xffff ); | |||
4266 | ||||
4267 | //cvAuto | |||
4268 | m_rWW8Export.InsUInt16( NS_sprm::PShd::val ); | |||
4269 | m_rWW8Export.pO->push_back( 10 ); | |||
4270 | m_rWW8Export.InsUInt32( 0xFF000000 ); | |||
4271 | m_rWW8Export.InsUInt32( 0xFF000000 ); | |||
4272 | m_rWW8Export.InsUInt16( 0x0000 ); | |||
4273 | } | |||
4274 | ||||
4275 | void WW8AttributeOutput::FormatFillGradient( const XFillGradientItem& /*rFillGradient*/ ) | |||
4276 | { | |||
4277 | } | |||
4278 | ||||
4279 | WW8_BRCVer9 WW8Export::TranslateBorderLine(const SvxBorderLine& rLine, | |||
4280 | sal_uInt16 nDist, bool bShadow) | |||
4281 | { | |||
4282 | sal_uInt32 nColBGR = 0; | |||
4283 | sal_uInt16 nWidth = ::editeng::ConvertBorderWidthToWord( | |||
4284 | rLine.GetBorderLineStyle(), rLine.GetWidth()); | |||
4285 | sal_uInt8 brcType = 0; | |||
4286 | ||||
4287 | if( nWidth ) // line ? | |||
4288 | { | |||
4289 | // BRC.brcType | |||
4290 | brcType = 0; | |||
4291 | // All the border types values are available on | |||
4292 | // http://msdn.microsoft.com/en-us/library/dd908142%28v=office.12%29.aspx | |||
4293 | switch (rLine.GetBorderLineStyle()) | |||
4294 | { | |||
4295 | case SvxBorderLineStyle::SOLID: | |||
4296 | { | |||
4297 | if ( rLine.GetWidth( ) == DEF_LINE_WIDTH_01 ) | |||
4298 | brcType = 5; | |||
4299 | else | |||
4300 | brcType = 1; | |||
4301 | } | |||
4302 | break; | |||
4303 | case SvxBorderLineStyle::DOTTED: | |||
4304 | brcType = 6; | |||
4305 | break; | |||
4306 | case SvxBorderLineStyle::DASHED: | |||
4307 | brcType = 7; | |||
4308 | break; | |||
4309 | case SvxBorderLineStyle::DOUBLE: | |||
4310 | case SvxBorderLineStyle::DOUBLE_THIN: | |||
4311 | brcType = 3; | |||
4312 | break; | |||
4313 | case SvxBorderLineStyle::THINTHICK_SMALLGAP: | |||
4314 | brcType = 11; | |||
4315 | break; | |||
4316 | case SvxBorderLineStyle::THINTHICK_MEDIUMGAP: | |||
4317 | brcType = 14; | |||
4318 | break; | |||
4319 | case SvxBorderLineStyle::THINTHICK_LARGEGAP: | |||
4320 | brcType = 17; | |||
4321 | break; | |||
4322 | case SvxBorderLineStyle::THICKTHIN_SMALLGAP: | |||
4323 | brcType = 12; | |||
4324 | break; | |||
4325 | case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP: | |||
4326 | brcType = 15; | |||
4327 | break; | |||
4328 | case SvxBorderLineStyle::THICKTHIN_LARGEGAP: | |||
4329 | brcType = 18; | |||
4330 | break; | |||
4331 | case SvxBorderLineStyle::EMBOSSED: | |||
4332 | brcType = 24; | |||
4333 | break; | |||
4334 | case SvxBorderLineStyle::ENGRAVED: | |||
4335 | brcType = 25; | |||
4336 | break; | |||
4337 | case SvxBorderLineStyle::OUTSET: | |||
4338 | brcType = 26; | |||
4339 | break; | |||
4340 | case SvxBorderLineStyle::INSET: | |||
4341 | brcType = 27; | |||
4342 | break; | |||
4343 | case SvxBorderLineStyle::FINE_DASHED: | |||
4344 | brcType = 22; | |||
4345 | break; | |||
4346 | case SvxBorderLineStyle::DASH_DOT: | |||
4347 | brcType = 8; | |||
4348 | break; | |||
4349 | case SvxBorderLineStyle::DASH_DOT_DOT: | |||
4350 | brcType = 9; | |||
4351 | break; | |||
4352 | default: | |||
4353 | break; | |||
4354 | } | |||
4355 | ||||
4356 | // convert width from twips (1/20 pt) to eighths of a point | |||
4357 | nWidth = (( nWidth * 8 ) + 10 ) / 20; | |||
4358 | if( 0xff < nWidth ) | |||
4359 | nWidth = 0xff; | |||
4360 | ||||
4361 | if( 0 == nWidth ) // really thin line | |||
4362 | nWidth = 1; // don't omit | |||
4363 | ||||
4364 | // BRC.cv | |||
4365 | nColBGR = wwUtility::RGBToBGR(rLine.GetColor().GetRGBColor()); | |||
4366 | } | |||
4367 | ||||
4368 | // BRC.dptSpace | |||
4369 | sal_uInt16 nLDist = nDist; | |||
4370 | nLDist /= 20; // unit of measurement: pt | |||
4371 | if( nLDist > 0x1f ) | |||
4372 | nLDist = 0x1f; | |||
4373 | ||||
4374 | return WW8_BRCVer9(nColBGR, sal_uInt8(nWidth), brcType, sal_uInt8(nLDist), | |||
4375 | bShadow, false); | |||
4376 | } | |||
4377 | ||||
4378 | /** | |||
4379 | * Gets passed a WW8Bytes*, so the function also can be used for the table border. | |||
4380 | * | |||
4381 | * @param nSprmNo If nSprmNo == 0, then the opcode isn't outputted. | |||
4382 | * @param bShadow SHOULDN'T be set for table cells ! | |||
4383 | */ | |||
4384 | void WW8Export::Out_BorderLine(ww::bytes& rO, const SvxBorderLine* pLine, | |||
4385 | sal_uInt16 nDist, sal_uInt16 nSprmNo, sal_uInt16 nSprmNoVer9, bool bShadow) | |||
4386 | { | |||
4387 | OSL_ENSURE( ( nSprmNo == 0 ) ||do { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false) | |||
4388 | ( nSprmNo >= 38 && nSprmNo <= 41 ) ||do { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false) | |||
4389 | ( nSprmNo >= NS_sprm::PBrcTop80::valdo { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false) | |||
4390 | && nSprmNo <= NS_sprm::PBrcRight80::val ) ||do { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false) | |||
4391 | ( nSprmNo >= NS_sprm::SBrcTop80::valdo { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false) | |||
4392 | && nSprmNo <= NS_sprm::SBrcRight80::val ),do { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false) | |||
4393 | "Sprm for border out is of range" )do { if (true && (!(( nSprmNo == 0 ) || ( nSprmNo >= 38 && nSprmNo <= 41 ) || ( nSprmNo >= NS_sprm:: PBrcTop80::val && nSprmNo <= NS_sprm::PBrcRight80:: val ) || ( nSprmNo >= NS_sprm::SBrcTop80::val && nSprmNo <= NS_sprm::SBrcRight80::val )))) { sal_detail_logFormat( (SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4393" ": "), "%s", "Sprm for border out is of range"); } } while (false); | |||
4394 | ||||
4395 | WW8_BRCVer9 aBrcVer9; | |||
4396 | WW8_BRC aBrcVer8; | |||
4397 | ||||
4398 | if( pLine && pLine->GetBorderLineStyle() != SvxBorderLineStyle::NONE ) | |||
4399 | { | |||
4400 | aBrcVer9 = TranslateBorderLine( *pLine, nDist, bShadow ); | |||
4401 | sal_uInt8 ico = msfilter::util::TransColToIco( msfilter::util::BGRToRGB(aBrcVer9.cv()) ); | |||
4402 | aBrcVer8 = WW8_BRC( aBrcVer9.dptLineWidth(), aBrcVer9.brcType(), ico, | |||
4403 | aBrcVer9.dptSpace(), aBrcVer9.fShadow(), aBrcVer9.fFrame() ); | |||
4404 | } | |||
4405 | ||||
4406 | // WW97-SprmIds | |||
4407 | if ( nSprmNo != 0 ) | |||
4408 | SwWW8Writer::InsUInt16( rO, nSprmNo ); | |||
4409 | ||||
4410 | rO.insert( rO.end(), aBrcVer8.aBits1, aBrcVer8.aBits2+2 ); | |||
4411 | ||||
4412 | if ( nSprmNoVer9 != 0 ) | |||
4413 | { | |||
4414 | SwWW8Writer::InsUInt16( rO, nSprmNoVer9 ); | |||
4415 | rO.push_back(sizeof(WW8_BRCVer9)); | |||
4416 | rO.insert( rO.end(), aBrcVer9.aBits1, aBrcVer9.aBits2+4); | |||
4417 | } | |||
4418 | } | |||
4419 | ||||
4420 | /** | |||
4421 | * is for all boxes except in tables. pO of the WW8Writer is used | |||
4422 | * | |||
4423 | * @param rBox | |||
4424 | * @param bShadow | |||
4425 | */ | |||
4426 | void WW8Export::Out_SwFormatBox(const SvxBoxItem& rBox, bool bShadow) | |||
4427 | { | |||
4428 | static const SvxBoxItemLine aBorders[] = | |||
4429 | { | |||
4430 | SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT | |||
4431 | }; | |||
4432 | static const sal_uInt16 aPBrc[] = | |||
4433 | { | |||
4434 | // WW8 SPRMs | |||
4435 | NS_sprm::PBrcTop80::val, NS_sprm::PBrcLeft80::val, | |||
4436 | NS_sprm::PBrcBottom80::val, NS_sprm::PBrcRight80::val, | |||
4437 | // WW9 SPRMs | |||
4438 | NS_sprm::PBrcTop::val, NS_sprm::PBrcLeft::val, | |||
4439 | NS_sprm::PBrcBottom::val, NS_sprm::PBrcRight::val | |||
4440 | }; | |||
4441 | static const sal_uInt16 aSBrc[] = | |||
4442 | { | |||
4443 | // WW8 SPRMs | |||
4444 | NS_sprm::SBrcTop80::val, NS_sprm::SBrcLeft80::val, | |||
4445 | NS_sprm::SBrcBottom80::val, NS_sprm::SBrcRight80::val, | |||
4446 | // WW9 SPRMs | |||
4447 | NS_sprm::SBrcTop::val, NS_sprm::SBrcLeft::val, | |||
4448 | NS_sprm::SBrcBottom::val, NS_sprm::SBrcRight::val | |||
4449 | }; | |||
4450 | ||||
4451 | const SvxBoxItemLine* pBrd = aBorders; | |||
4452 | for( sal_uInt16 i = 0; i < 4; ++i, ++pBrd ) | |||
4453 | { | |||
4454 | const SvxBorderLine* pLn = rBox.GetLine( *pBrd ); | |||
4455 | ||||
4456 | sal_uInt16 nSprmNo, nSprmNoVer9 = 0; | |||
4457 | if (m_bOutPageDescs) | |||
4458 | { | |||
4459 | nSprmNo = aSBrc[i]; | |||
4460 | nSprmNoVer9 = aSBrc[i+4]; | |||
4461 | } | |||
4462 | else | |||
4463 | { | |||
4464 | nSprmNo = aPBrc[i]; | |||
4465 | nSprmNoVer9 = aPBrc[i+4]; | |||
4466 | } | |||
4467 | ||||
4468 | Out_BorderLine( *pO, pLn, rBox.GetDistance( *pBrd ), nSprmNo, | |||
4469 | nSprmNoVer9, bShadow ); | |||
4470 | } | |||
4471 | } | |||
4472 | ||||
4473 | /** | |||
4474 | * FormatBox2() is for TC structures in tables. The Sprm opcode isn't written | |||
4475 | * because it is packed into the TC structure without opcode. | |||
4476 | * dxpSpace always becomes 0, because WW requires that in tables | |||
4477 | * ( table borders otherwise will fray ) | |||
4478 | * | |||
4479 | * @param rO A WW8Bytes pointer is passed in as output parameter | |||
4480 | */ | |||
4481 | void WW8Export::Out_SwFormatTableBox( ww::bytes& rO, const SvxBoxItem * pBox ) | |||
4482 | { | |||
4483 | // possible and maybe better would be 0xffff | |||
4484 | static const SvxBoxItemLine aBorders[] = | |||
4485 | { | |||
4486 | SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT | |||
4487 | }; | |||
4488 | static const SvxBorderLine aBorderLine; | |||
4489 | ||||
4490 | for(const SvxBoxItemLine & rBorder : aBorders) | |||
4491 | { | |||
4492 | const SvxBorderLine* pLn; | |||
4493 | if (pBox != nullptr) | |||
4494 | pLn = pBox->GetLine( rBorder ); | |||
4495 | else | |||
4496 | pLn = & aBorderLine; | |||
4497 | ||||
4498 | Out_BorderLine(rO, pLn, 0, 0, 0, false); | |||
4499 | } | |||
4500 | } | |||
4501 | ||||
4502 | void WW8Export::Out_CellRangeBorders( const SvxBoxItem * pBox, sal_uInt8 nStart, | |||
4503 | sal_uInt8 nLimit ) | |||
4504 | { | |||
4505 | if ( !pBox ) | |||
4506 | return; | |||
4507 | ||||
4508 | static const SvxBoxItemLine aBorders[] = | |||
4509 | { | |||
4510 | SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::RIGHT | |||
4511 | }; | |||
4512 | ||||
4513 | for( int i = 0; i < 4; ++i ) | |||
4514 | { | |||
4515 | const SvxBorderLine* pLn = pBox->GetLine( aBorders[i] ); | |||
4516 | if (!pLn) | |||
4517 | continue; | |||
4518 | ||||
4519 | InsUInt16( NS_sprm::TSetBrc::val ); | |||
4520 | pO->push_back( 11 ); | |||
4521 | pO->push_back( nStart ); | |||
4522 | pO->push_back( nLimit ); | |||
4523 | pO->push_back( 1<<i ); | |||
4524 | WW8_BRCVer9 aBrcVer9 = TranslateBorderLine( *pLn, 0, false ); | |||
4525 | pO->insert( pO->end(), aBrcVer9.aBits1, aBrcVer9.aBits2+4 ); | |||
4526 | } | |||
4527 | } | |||
4528 | ||||
4529 | void WW8AttributeOutput::FormatBox( const SvxBoxItem& rBox ) | |||
4530 | { | |||
4531 | // Fly around graphic -> here no border, because the | |||
4532 | // graphics header already has the border | |||
4533 | if ( m_rWW8Export.m_bOutGrf ) | |||
4534 | return; | |||
4535 | ||||
4536 | bool bShadow = false; | |||
4537 | const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_SHADOW ); | |||
4538 | if ( pItem ) | |||
4539 | { | |||
4540 | const SvxShadowItem* p = static_cast<const SvxShadowItem*>(pItem); | |||
4541 | bShadow = ( p->GetLocation() != SvxShadowLocation::NONE ) | |||
4542 | && ( p->GetWidth() != 0 ); | |||
4543 | } | |||
4544 | ||||
4545 | SvxBoxItem aBox(rBox); | |||
4546 | if (m_rWW8Export.m_bOutPageDescs) | |||
4547 | { | |||
4548 | editeng::WordBorderDistances aDistances; | |||
4549 | editeng::BorderDistancesToWord(aBox, m_pageMargins, aDistances); | |||
4550 | ||||
4551 | aBox.SetDistance(aDistances.nTop, SvxBoxItemLine::TOP); | |||
4552 | aBox.SetDistance(aDistances.nLeft, SvxBoxItemLine::LEFT); | |||
4553 | aBox.SetDistance(aDistances.nBottom, SvxBoxItemLine::BOTTOM); | |||
4554 | aBox.SetDistance(aDistances.nRight, SvxBoxItemLine::RIGHT); | |||
4555 | ||||
4556 | m_bFromEdge = aDistances.bFromEdge; | |||
4557 | } | |||
4558 | ||||
4559 | m_rWW8Export.Out_SwFormatBox( aBox, bShadow ); | |||
4560 | } | |||
4561 | ||||
4562 | SwTwips WW8Export::CurrentPageWidth(SwTwips &rLeft, SwTwips &rRight) const | |||
4563 | { | |||
4564 | const SwFrameFormat* pFormat = m_pCurrentPageDesc ? &m_pCurrentPageDesc->GetMaster() | |||
4565 | : &m_rDoc.GetPageDesc(0).GetMaster(); | |||
4566 | ||||
4567 | const SvxLRSpaceItem& rLR = pFormat->GetLRSpace(); | |||
4568 | SwTwips nPageSize = pFormat->GetFrameSize().GetWidth(); | |||
4569 | rLeft = rLR.GetLeft(); | |||
4570 | rRight = rLR.GetRight(); | |||
4571 | return nPageSize; | |||
4572 | } | |||
4573 | ||||
4574 | void WW8AttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFormatCol & rCol, bool bEven, SwTwips nPageSize ) | |||
4575 | { | |||
4576 | // CColumns | |||
4577 | m_rWW8Export.InsUInt16( NS_sprm::SCcolumns::val ); | |||
4578 | m_rWW8Export.InsUInt16( nCols - 1 ); | |||
4579 | ||||
4580 | // DxaColumns | |||
4581 | m_rWW8Export.InsUInt16( NS_sprm::SDxaColumns::val ); | |||
4582 | m_rWW8Export.InsUInt16( rCol.GetGutterWidth( true ) ); | |||
4583 | ||||
4584 | // LBetween | |||
4585 | m_rWW8Export.InsUInt16( NS_sprm::SLBetween::val ); | |||
4586 | m_rWW8Export.pO->push_back( COLADJ_NONE == rCol.GetLineAdj( )? 0 : 1 ); | |||
4587 | ||||
4588 | const SwColumns & rColumns = rCol.GetColumns( ); | |||
4589 | ||||
4590 | // FEvenlySpaced | |||
4591 | m_rWW8Export.InsUInt16( NS_sprm::SFEvenlySpaced::val ); | |||
4592 | m_rWW8Export.pO->push_back( bEven ? 1 : 0 ); | |||
4593 | ||||
4594 | if ( bEven ) | |||
4595 | return; | |||
4596 | ||||
4597 | for ( sal_uInt16 n = 0; n < nCols; ++n ) | |||
4598 | { | |||
4599 | //sprmSDxaColWidth | |||
4600 | m_rWW8Export.InsUInt16( NS_sprm::SDxaColWidth::val ); | |||
4601 | m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(n) ); | |||
4602 | m_rWW8Export.InsUInt16( rCol. | |||
4603 | CalcPrtColWidth( n, | |||
4604 | static_cast<sal_uInt16>(nPageSize) ) ); | |||
4605 | ||||
4606 | if ( n + 1 != nCols ) | |||
4607 | { | |||
4608 | //sprmSDxaColSpacing | |||
4609 | m_rWW8Export.InsUInt16( NS_sprm::SDxaColSpacing::val ); | |||
4610 | m_rWW8Export.pO->push_back( static_cast<sal_uInt8>(n) ); | |||
4611 | m_rWW8Export.InsUInt16( rColumns[n].GetRight( ) + | |||
4612 | rColumns[n + 1].GetLeft( ) ); | |||
4613 | } | |||
4614 | } | |||
4615 | } | |||
4616 | ||||
4617 | void AttributeOutputBase::FormatColumns( const SwFormatCol& rCol ) | |||
4618 | { | |||
4619 | const SwColumns& rColumns = rCol.GetColumns(); | |||
4620 | ||||
4621 | sal_uInt16 nCols = rColumns.size(); | |||
4622 | if (1 >= nCols || GetExport( ).m_bOutFlyFrameAttrs) | |||
4623 | return; | |||
4624 | ||||
4625 | // get the page width without borders !! | |||
4626 | ||||
4627 | const SwFrameFormat* pFormat = GetExport( ).m_pCurrentPageDesc ? &GetExport( ).m_pCurrentPageDesc->GetMaster() : &const_cast<const SwDoc&>(GetExport().m_rDoc).GetPageDesc(0).GetMaster(); | |||
4628 | const SvxFrameDirectionItem &frameDirection = pFormat->GetFrameDir(); | |||
4629 | SwTwips nPageSize; | |||
4630 | if ( frameDirection.GetValue() == SvxFrameDirection::Vertical_RL_TB || frameDirection.GetValue() == SvxFrameDirection::Vertical_LR_TB ) | |||
4631 | { | |||
4632 | const SvxULSpaceItem &rUL = pFormat->GetULSpace(); | |||
4633 | nPageSize = pFormat->GetFrameSize().GetHeight(); | |||
4634 | nPageSize -= rUL.GetUpper() + rUL.GetLower(); | |||
4635 | ||||
4636 | const SwFormatHeader *header = pFormat->GetAttrSet().GetItem(RES_HEADER); | |||
4637 | if ( header ) | |||
4638 | { | |||
4639 | const SwFrameFormat *headerFormat = header->GetHeaderFormat(); | |||
4640 | if (headerFormat) | |||
4641 | { | |||
4642 | nPageSize -= headerFormat->GetFrameSize().GetHeight(); | |||
4643 | } | |||
4644 | } | |||
4645 | const SwFormatFooter *footer = pFormat->GetAttrSet().GetItem(RES_FOOTER); | |||
4646 | if ( footer ) | |||
4647 | { | |||
4648 | const SwFrameFormat *footerFormat = footer->GetFooterFormat(); | |||
4649 | if ( footerFormat ) | |||
4650 | { | |||
4651 | nPageSize -= footerFormat->GetFrameSize().GetHeight(); | |||
4652 | } | |||
4653 | } | |||
4654 | } | |||
4655 | else | |||
4656 | { | |||
4657 | const SvxLRSpaceItem &rLR = pFormat->GetLRSpace(); | |||
4658 | nPageSize = pFormat->GetFrameSize().GetWidth(); | |||
4659 | nPageSize -= rLR.GetLeft() + rLR.GetRight(); | |||
4660 | //i120133: The Section width should consider page indent value. | |||
4661 | nPageSize -= rCol.GetAdjustValue(); | |||
4662 | ||||
4663 | } | |||
4664 | ||||
4665 | // look if all columns are equal | |||
4666 | bool bEven = true; | |||
4667 | sal_uInt16 n; | |||
4668 | sal_uInt16 nColWidth = rCol.CalcPrtColWidth( 0, static_cast<sal_uInt16>(nPageSize) ); | |||
4669 | for ( n = 1; n < nCols; n++ ) | |||
4670 | { | |||
4671 | short nDiff = nColWidth - | |||
4672 | rCol.CalcPrtColWidth( n, static_cast<sal_uInt16>(nPageSize) ); | |||
4673 | ||||
4674 | if ( nDiff > 10 || nDiff < -10 ) // Tolerance: 10 tw | |||
4675 | { | |||
4676 | bEven = false; | |||
4677 | break; | |||
4678 | } | |||
4679 | } | |||
4680 | ||||
4681 | FormatColumns_Impl( nCols, rCol, bEven, nPageSize ); | |||
4682 | } | |||
4683 | ||||
4684 | // "Paragraphs together" | |||
4685 | void WW8AttributeOutput::FormatKeep( const SvxFormatKeepItem& rKeep ) | |||
4686 | { | |||
4687 | // sprmFKeepFollow | |||
4688 | m_rWW8Export.InsUInt16( NS_sprm::PFKeepFollow::val ); | |||
4689 | ||||
4690 | m_rWW8Export.pO->push_back( rKeep.GetValue() ? 1 : 0 ); | |||
4691 | } | |||
4692 | ||||
4693 | // exclude a paragraph from Line Numbering | |||
4694 | void WW8AttributeOutput::FormatLineNumbering( const SwFormatLineNumber& rNumbering ) | |||
4695 | { | |||
4696 | // sprmPFNoLineNumb | |||
4697 | m_rWW8Export.InsUInt16( NS_sprm::PFNoLineNumb::val ); | |||
4698 | ||||
4699 | m_rWW8Export.pO->push_back( rNumbering.IsCount() ? 0 : 1 ); | |||
4700 | } | |||
4701 | ||||
4702 | /* File PARATR.HXX */ | |||
4703 | ||||
4704 | void WW8AttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti ) | |||
4705 | { | |||
4706 | // sprmPDyaLine | |||
4707 | m_rWW8Export.InsUInt16( NS_sprm::PDyaLine::val ); | |||
4708 | ||||
4709 | m_rWW8Export.InsUInt16( nSpace ); | |||
4710 | m_rWW8Export.InsUInt16( nMulti ); | |||
4711 | } | |||
4712 | ||||
4713 | void AttributeOutputBase::ParaLineSpacing( const SvxLineSpacingItem& rSpacing ) | |||
4714 | { | |||
4715 | short nSpace = 240, nMulti = 0; | |||
4716 | ||||
4717 | switch ( rSpacing.GetLineSpaceRule() ) | |||
4718 | { | |||
4719 | default: | |||
4720 | break; | |||
4721 | case SvxLineSpaceRule::Fix: // Fix | |||
4722 | nSpace = -static_cast<short>(rSpacing.GetLineHeight()); | |||
4723 | break; | |||
4724 | case SvxLineSpaceRule::Min: // At least | |||
4725 | nSpace = static_cast<short>(rSpacing.GetLineHeight()); | |||
4726 | break; | |||
4727 | case SvxLineSpaceRule::Auto: | |||
4728 | { | |||
4729 | if( rSpacing.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) // Leading | |||
4730 | { | |||
4731 | // doesn't exist in WW - how do you get the MaxLineHeight? | |||
4732 | nSpace = rSpacing.GetInterLineSpace(); | |||
4733 | sal_uInt16 nScript = | |||
4734 | i18n::ScriptType::LATIN; | |||
4735 | const SwAttrSet *pSet = nullptr; | |||
4736 | if ( auto pFormat = dynamic_cast< const SwFormat *>( GetExport().m_pOutFormatNode ) ) | |||
4737 | { | |||
4738 | pSet = &pFormat->GetAttrSet(); | |||
4739 | } | |||
4740 | else if ( auto pNd = dynamic_cast< const SwTextNode *>( GetExport().m_pOutFormatNode ) ) | |||
4741 | { | |||
4742 | pSet = &pNd->GetSwAttrSet(); | |||
4743 | nScript = g_pBreakIt->GetBreakIter()->getScriptType(pNd->GetText(), 0); | |||
4744 | } | |||
4745 | OSL_ENSURE( pSet, "No attrset for lineheight :-(" )do { if (true && (!(pSet))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN ), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4745" ": "), "%s", "No attrset for lineheight :-("); } } while (false); | |||
4746 | if ( pSet ) | |||
4747 | { | |||
4748 | nSpace = nSpace + static_cast<short>( AttrSetToLineHeight( GetExport().m_rDoc.getIDocumentSettingAccess(), | |||
4749 | *pSet, *Application::GetDefaultDevice(), nScript ) ); | |||
4750 | } | |||
4751 | } | |||
4752 | else // Proportional | |||
4753 | { | |||
4754 | if ( rSpacing.GetInterLineSpaceRule() != SvxInterLineSpaceRule::Off ) | |||
4755 | nSpace = static_cast<short>( ( 240L * rSpacing.GetPropLineSpace() ) / 100L ); | |||
4756 | nMulti = 1; | |||
4757 | } | |||
4758 | } | |||
4759 | break; | |||
4760 | } | |||
4761 | // if nSpace is negative, it is a fixed size in 1/20 of a point | |||
4762 | // if nSpace is positive and nMulti is 1, it is 1/240 of a single line height | |||
4763 | // otherwise, it is a minimum size in 1/20 of a point | |||
4764 | ParaLineSpacing_Impl( nSpace, nMulti ); | |||
4765 | } | |||
4766 | ||||
4767 | void WW8AttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust ) | |||
4768 | { | |||
4769 | // sprmPJc | |||
4770 | sal_uInt8 nAdj; | |||
4771 | sal_uInt8 nAdjBiDi; | |||
4772 | switch ( rAdjust.GetAdjust() ) | |||
4773 | { | |||
4774 | case SvxAdjust::Left: | |||
4775 | nAdj = 0; | |||
4776 | nAdjBiDi = 2; | |||
4777 | break; | |||
4778 | case SvxAdjust::Right: | |||
4779 | nAdj = 2; | |||
4780 | nAdjBiDi = 0; | |||
4781 | break; | |||
4782 | case SvxAdjust::BlockLine: | |||
4783 | case SvxAdjust::Block: | |||
4784 | nAdj = nAdjBiDi = 3; | |||
4785 | break; | |||
4786 | case SvxAdjust::Center: | |||
4787 | nAdj = nAdjBiDi = 1; | |||
4788 | break; | |||
4789 | default: | |||
4790 | return; // not a supported Attribute | |||
4791 | } | |||
4792 | ||||
4793 | m_rWW8Export.InsUInt16(NS_sprm::PJc80::val); | |||
4794 | m_rWW8Export.pO->push_back(nAdj); | |||
4795 | ||||
4796 | /* | |||
4797 | Sadly for left to right paragraphs both these values are the same, | |||
4798 | for right to left paragraphs the bidi one is the reverse of the | |||
4799 | normal one. | |||
4800 | */ | |||
4801 | m_rWW8Export.InsUInt16(NS_sprm::PJc::val); //bidi version ? | |||
4802 | bool bBiDiSwap = false; | |||
4803 | if (m_rWW8Export.m_pOutFormatNode) | |||
4804 | { | |||
4805 | SvxFrameDirection nDirection = SvxFrameDirection::Horizontal_LR_TB; | |||
4806 | if (dynamic_cast<const SwTextNode*>(m_rWW8Export.m_pOutFormatNode) != nullptr) | |||
4807 | { | |||
4808 | SwPosition aPos(*static_cast<const SwContentNode*>(m_rWW8Export.m_pOutFormatNode)); | |||
4809 | nDirection = m_rWW8Export.m_rDoc.GetTextDirection(aPos); | |||
4810 | } | |||
4811 | else if (dynamic_cast<const SwTextFormatColl*>(m_rWW8Export.m_pOutFormatNode) != nullptr) | |||
4812 | { | |||
4813 | const SwTextFormatColl* pC = | |||
4814 | static_cast<const SwTextFormatColl*>(m_rWW8Export.m_pOutFormatNode); | |||
4815 | const SvxFrameDirectionItem &rItem = | |||
4816 | ItemGet<SvxFrameDirectionItem>(*pC, RES_FRAMEDIR); | |||
4817 | nDirection = rItem.GetValue(); | |||
4818 | } | |||
4819 | if ( ( nDirection == SvxFrameDirection::Horizontal_RL_TB ) || | |||
4820 | ( nDirection == SvxFrameDirection::Environment && AllSettings::GetLayoutRTL() ) ) | |||
4821 | { | |||
4822 | bBiDiSwap = true; | |||
4823 | } | |||
4824 | } | |||
4825 | ||||
4826 | if (bBiDiSwap) | |||
4827 | m_rWW8Export.pO->push_back(nAdjBiDi); | |||
4828 | else | |||
4829 | m_rWW8Export.pO->push_back(nAdj); | |||
4830 | } | |||
4831 | ||||
4832 | void WW8AttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection ) | |||
4833 | { | |||
4834 | sal_uInt16 nTextFlow=0; | |||
4835 | bool bBiDi = false; | |||
4836 | SvxFrameDirection nDir = rDirection.GetValue(); | |||
4837 | ||||
4838 | if ( nDir == SvxFrameDirection::Environment ) | |||
4839 | nDir = GetExport( ).GetDefaultFrameDirection( ); | |||
4840 | ||||
4841 | ||||
4842 | switch ( nDir ) | |||
4843 | { | |||
4844 | default: | |||
4845 | //Can't get an unknown type here | |||
4846 | OSL_FAIL("Unknown frame direction")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "4846" ": "), "%s", "Unknown frame direction"); } } while (false); | |||
4847 | [[fallthrough]]; | |||
4848 | case SvxFrameDirection::Horizontal_LR_TB: | |||
4849 | nTextFlow = 0; | |||
4850 | break; | |||
4851 | case SvxFrameDirection::Horizontal_RL_TB: | |||
4852 | nTextFlow = 0; | |||
4853 | bBiDi = true; | |||
4854 | break; | |||
4855 | case SvxFrameDirection::Vertical_LR_TB: //word doesn't have this | |||
4856 | case SvxFrameDirection::Vertical_RL_TB: | |||
4857 | nTextFlow = 1; | |||
4858 | break; | |||
4859 | } | |||
4860 | ||||
4861 | if ( m_rWW8Export.m_bOutPageDescs ) | |||
4862 | { | |||
4863 | m_rWW8Export.InsUInt16( NS_sprm::STextFlow::val ); | |||
4864 | m_rWW8Export.InsUInt16( nTextFlow ); | |||
4865 | m_rWW8Export.InsUInt16( NS_sprm::SFBiDi::val ); | |||
4866 | m_rWW8Export.pO->push_back( bBiDi ? 1 : 0 ); | |||
4867 | } | |||
4868 | else if ( !m_rWW8Export.m_bOutFlyFrameAttrs ) //paragraph/style | |||
4869 | { | |||
4870 | m_rWW8Export.InsUInt16( NS_sprm::PFBiDi::val ); | |||
4871 | m_rWW8Export.pO->push_back( bBiDi ? 1 : 0 ); | |||
4872 | } | |||
4873 | } | |||
4874 | ||||
4875 | void WW8AttributeOutput::ParaGrabBag(const SfxGrabBagItem& /*rItem*/) | |||
4876 | { | |||
4877 | } | |||
4878 | ||||
4879 | void WW8AttributeOutput::CharGrabBag(const SfxGrabBagItem& /*rItem*/) | |||
4880 | { | |||
4881 | } | |||
4882 | ||||
4883 | void WW8AttributeOutput::ParaOutlineLevel(const SfxUInt16Item& /*rItem*/) | |||
4884 | { | |||
4885 | } | |||
4886 | ||||
4887 | // "Separate paragraphs" | |||
4888 | void WW8AttributeOutput::ParaSplit( const SvxFormatSplitItem& rSplit ) | |||
4889 | { | |||
4890 | // sprmPFKeep | |||
4891 | m_rWW8Export.InsUInt16( NS_sprm::PFKeep::val ); | |||
4892 | m_rWW8Export.pO->push_back( rSplit.GetValue() ? 0 : 1 ); | |||
4893 | } | |||
4894 | ||||
4895 | /** | |||
4896 | * Only convert the item "SvxWidowItem" and not the orphans, because | |||
4897 | * in WW only one attribute "paragraph control" exists for both and | |||
4898 | * in SW probably both or none is set by the user. | |||
4899 | */ | |||
4900 | void WW8AttributeOutput::ParaWidows( const SvxWidowsItem& rWidows ) | |||
4901 | { | |||
4902 | // sprmPFWidowControl | |||
4903 | m_rWW8Export.InsUInt16( NS_sprm::PFWidowControl::val ); | |||
4904 | m_rWW8Export.pO->push_back( rWidows.GetValue() ? 1 : 0 ); | |||
4905 | } | |||
4906 | ||||
4907 | namespace { | |||
4908 | ||||
4909 | class SwWW8WrTabu | |||
4910 | { | |||
4911 | std::unique_ptr<sal_uInt8[]> pDel; // DelArray | |||
4912 | std::unique_ptr<sal_uInt8[]> pAddPos; // AddPos-Array | |||
4913 | std::unique_ptr<sal_uInt8[]> pAddTyp; // AddTyp-Array | |||
4914 | sal_uInt16 nAdd; // number of tabs to be added | |||
4915 | sal_uInt16 nDel; // number of tabs to be deleted | |||
4916 | ||||
4917 | SwWW8WrTabu(const SwWW8WrTabu&) = delete; | |||
4918 | SwWW8WrTabu& operator=(const SwWW8WrTabu&) = delete; | |||
4919 | ||||
4920 | public: | |||
4921 | SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax); | |||
4922 | ||||
4923 | void Add(const SvxTabStop &rTS, long nAdjustment); | |||
4924 | void Del(const SvxTabStop &rTS, long nAdjustment); | |||
4925 | void PutAll(WW8Export& rWW8Wrt); | |||
4926 | }; | |||
4927 | ||||
4928 | } | |||
4929 | ||||
4930 | SwWW8WrTabu::SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax) | |||
4931 | : nAdd(0), nDel(0) | |||
4932 | { | |||
4933 | if (nDelMax) | |||
4934 | pDel.reset( new sal_uInt8[nDelMax * 2] ); | |||
4935 | pAddPos.reset( new sal_uInt8[nAddMax * 2] ); | |||
4936 | pAddTyp.reset( new sal_uInt8[nAddMax] ); | |||
4937 | } | |||
4938 | ||||
4939 | /** | |||
4940 | * insert a tab in the WW structure | |||
4941 | */ | |||
4942 | void SwWW8WrTabu::Add(const SvxTabStop & rTS, long nAdjustment) | |||
4943 | { | |||
4944 | // insert tab position | |||
4945 | ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment), | |||
4946 | pAddPos.get() + (nAdd * 2)); | |||
4947 | ||||
4948 | // insert tab type | |||
4949 | sal_uInt8 nPara = 0; | |||
4950 | switch (rTS.GetAdjustment()) | |||
4951 | { | |||
4952 | case SvxTabAdjust::Right: | |||
4953 | nPara = 2; | |||
4954 | break; | |||
4955 | case SvxTabAdjust::Center: | |||
4956 | nPara = 1; | |||
4957 | break; | |||
4958 | case SvxTabAdjust::Decimal: | |||
4959 | /* | |||
4960 | There is nothing we can do btw the decimal separator has been | |||
4961 | customized, but if you think different remember that different | |||
4962 | locales have different separators, i.e. german is a , while english | |||
4963 | is a . | |||
4964 | */ | |||
4965 | nPara = 3; | |||
4966 | break; | |||
4967 | default: | |||
4968 | break; | |||
4969 | } | |||
4970 | ||||
4971 | switch( rTS.GetFill() ) | |||
4972 | { | |||
4973 | case '.': // dotted leader | |||
4974 | nPara |= 1 << 3; | |||
4975 | break; | |||
4976 | case '_': // Single line leader | |||
4977 | nPara |= 3 << 3; | |||
4978 | break; | |||
4979 | case '-': // hyphenated leader | |||
4980 | nPara |= 2 << 3; | |||
4981 | break; | |||
4982 | case '=': // heavy line leader | |||
4983 | nPara |= 4 << 3; | |||
4984 | break; | |||
4985 | } | |||
4986 | ||||
4987 | pAddTyp[nAdd] = nPara; | |||
4988 | ++nAdd; | |||
4989 | } | |||
4990 | ||||
4991 | /** | |||
4992 | * Insert a to be deleted tab in the WW structure | |||
4993 | */ | |||
4994 | void SwWW8WrTabu::Del(const SvxTabStop &rTS, long nAdjustment) | |||
4995 | { | |||
4996 | // insert tab position | |||
4997 | ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment), | |||
4998 | pDel.get() + (nDel * 2)); | |||
4999 | ++nDel; | |||
5000 | } | |||
5001 | ||||
5002 | /** | |||
5003 | * Writes the attribute to rWrt.pO | |||
5004 | */ | |||
5005 | void SwWW8WrTabu::PutAll(WW8Export& rWrt) | |||
5006 | { | |||
5007 | if (!nAdd && !nDel) //If it's a no-op | |||
5008 | return; | |||
5009 | OSL_ENSURE(nAdd <= 255, "more than 255 added tabstops?")do { if (true && (!(nAdd <= 255))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "5009" ": "), "%s", "more than 255 added tabstops?"); } } while (false); | |||
5010 | OSL_ENSURE(nDel <= 255, "more than 244 removed tabstops?")do { if (true && (!(nDel <= 255))) { sal_detail_logFormat ((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "5010" ": "), "%s", "more than 244 removed tabstops?"); } } while (false); | |||
5011 | if (nAdd > 255) | |||
5012 | nAdd = 255; | |||
5013 | if (nDel > 255) | |||
5014 | nDel = 255; | |||
5015 | ||||
5016 | sal_uInt16 nSiz = 2 * nDel + 3 * nAdd + 2; | |||
5017 | if (nSiz > 255) | |||
5018 | nSiz = 255; | |||
5019 | ||||
5020 | rWrt.InsUInt16(NS_sprm::PChgTabsPapx::val); | |||
5021 | // insert cch | |||
5022 | rWrt.pO->push_back(msword_cast<sal_uInt8>(nSiz)); | |||
5023 | // write DelArr | |||
5024 | rWrt.pO->push_back(msword_cast<sal_uInt8>(nDel)); | |||
5025 | rWrt.OutSprmBytes(pDel.get(), nDel * 2); | |||
5026 | // write InsArr | |||
5027 | rWrt.pO->push_back(msword_cast<sal_uInt8>(nAdd)); | |||
5028 | rWrt.OutSprmBytes(pAddPos.get(), 2 * nAdd); // AddPosArray | |||
5029 | rWrt.OutSprmBytes(pAddTyp.get(), nAdd); // AddTypArray | |||
5030 | } | |||
5031 | ||||
5032 | static void ParaTabStopAdd( WW8Export& rWrt, | |||
5033 | const SvxTabStopItem& rTStops, | |||
5034 | const long nLParaMgn ) | |||
5035 | { | |||
5036 | SwWW8WrTabu aTab( 0, rTStops.Count()); | |||
5037 | ||||
5038 | for( sal_uInt16 n = 0; n < rTStops.Count(); n++ ) | |||
5039 | { | |||
5040 | const SvxTabStop& rTS = rTStops[n]; | |||
5041 | // ignore default tabs | |||
5042 | if (SvxTabAdjust::Default != rTS.GetAdjustment()) | |||
5043 | aTab.Add(rTS, nLParaMgn); | |||
5044 | } | |||
5045 | aTab.PutAll( rWrt ); | |||
5046 | } | |||
5047 | ||||
5048 | static bool lcl_IsEqual(long nOneLeft, const SvxTabStop &rOne, | |||
5049 | long nTwoLeft, const SvxTabStop &rTwo) | |||
5050 | { | |||
5051 | return( | |||
5052 | nOneLeft == nTwoLeft && | |||
5053 | rOne.GetAdjustment() == rTwo.GetAdjustment() && | |||
5054 | rOne.GetDecimal() == rTwo.GetDecimal() && | |||
5055 | rOne.GetFill() == rTwo.GetFill() | |||
5056 | ); | |||
5057 | } | |||
5058 | ||||
5059 | static void ParaTabStopDelAdd( WW8Export& rWrt, | |||
5060 | const SvxTabStopItem& rTStyle, | |||
5061 | const long nLStypeMgn, | |||
5062 | const SvxTabStopItem& rTNew, | |||
5063 | const long nLParaMgn ) | |||
5064 | { | |||
5065 | SwWW8WrTabu aTab(rTStyle.Count(), rTNew.Count()); | |||
5066 | ||||
5067 | sal_uInt16 nO = 0; // rTStyle Index | |||
5068 | sal_uInt16 nN = 0; // rTNew Index | |||
5069 | ||||
5070 | do { | |||
5071 | const SvxTabStop* pTO; | |||
5072 | long nOP; | |||
5073 | if( nO < rTStyle.Count() ) // old not yet at the end? | |||
5074 | { | |||
5075 | pTO = &rTStyle[ nO ]; | |||
5076 | nOP = pTO->GetTabPos() + nLStypeMgn; | |||
5077 | if( SvxTabAdjust::Default == pTO->GetAdjustment() ) | |||
5078 | { | |||
5079 | nO++; // ignore default tab | |||
5080 | continue; | |||
5081 | } | |||
5082 | } | |||
5083 | else | |||
5084 | { | |||
5085 | pTO = nullptr; | |||
5086 | nOP = LONG_MAX9223372036854775807L; | |||
5087 | } | |||
5088 | ||||
5089 | const SvxTabStop* pTN; | |||
5090 | long nNP; | |||
5091 | if( nN < rTNew.Count() ) // new not yet at the end | |||
5092 | { | |||
5093 | pTN = &rTNew[ nN ]; | |||
5094 | nNP = pTN->GetTabPos() + nLParaMgn; | |||
5095 | if( SvxTabAdjust::Default == pTN->GetAdjustment() ) | |||
5096 | { | |||
5097 | nN++; // ignore default tab | |||
5098 | continue; | |||
5099 | } | |||
5100 | } | |||
5101 | else | |||
5102 | { | |||
5103 | pTN = nullptr; | |||
5104 | nNP = LONG_MAX9223372036854775807L; | |||
5105 | } | |||
5106 | ||||
5107 | if( nOP == LONG_MAX9223372036854775807L && nNP == LONG_MAX9223372036854775807L ) | |||
5108 | break; // everything done | |||
5109 | ||||
5110 | if( nOP < nNP ) // next tab is old | |||
5111 | { | |||
5112 | assert(pTO)(static_cast <bool> (pTO) ? void (0) : __assert_fail ("pTO" , "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 5112, __extension__ __PRETTY_FUNCTION__)); | |||
5113 | aTab.Del(*pTO, nLStypeMgn); // must be deleted | |||
5114 | nO++; | |||
5115 | } | |||
5116 | else if( nNP < nOP ) // next tab is new | |||
5117 | { | |||
5118 | assert(pTN)(static_cast <bool> (pTN) ? void (0) : __assert_fail ("pTN" , "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 5118, __extension__ __PRETTY_FUNCTION__)); | |||
5119 | aTab.Add(*pTN, nLParaMgn); // must be inserted | |||
5120 | nN++; | |||
5121 | } | |||
5122 | else if (lcl_IsEqual(nOP, *pTO, nNP, *pTN)) // tabs are equal | |||
5123 | { | |||
5124 | nO++; // nothing to do | |||
5125 | nN++; | |||
5126 | } | |||
5127 | else // tabs same position, different type | |||
5128 | { | |||
5129 | aTab.Del(*pTO, nLStypeMgn); // delete old one | |||
5130 | aTab.Add(*pTN, nLParaMgn); // insert new one | |||
5131 | nO++; | |||
5132 | nN++; | |||
5133 | } | |||
5134 | } while( true ); | |||
5135 | ||||
5136 | aTab.PutAll( rWrt ); | |||
5137 | } | |||
5138 | ||||
5139 | void WW8AttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStops ) | |||
5140 | { | |||
5141 | const bool bTabsRelativeToIndex = m_rWW8Export.m_pCurPam->GetDoc().getIDocumentSettingAccess().get( DocumentSettingId::TABS_RELATIVE_TO_INDENT ); | |||
5142 | ||||
5143 | long nCurrentLeft = 0; | |||
5144 | if ( bTabsRelativeToIndex ) | |||
5145 | { | |||
5146 | const SfxPoolItem* pLR = m_rWW8Export.HasItem( RES_LR_SPACE ); | |||
5147 | ||||
5148 | if ( pLR != nullptr ) | |||
5149 | nCurrentLeft = static_cast<const SvxLRSpaceItem*>(pLR)->GetTextLeft(); | |||
5150 | } | |||
5151 | ||||
5152 | // #i100264# | |||
5153 | if ( m_rWW8Export.m_bStyDef && | |||
5154 | m_rWW8Export.m_pCurrentStyle != nullptr && | |||
5155 | m_rWW8Export.m_pCurrentStyle->DerivedFrom() != nullptr ) | |||
5156 | { | |||
5157 | SvxTabStopItem aParentTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP ); | |||
5158 | const SwFormat *pParentStyle = m_rWW8Export.m_pCurrentStyle->DerivedFrom(); | |||
5159 | { | |||
5160 | if (const SvxTabStopItem* pParentTabs = pParentStyle->GetAttrSet().GetItem<SvxTabStopItem>(RES_PARATR_TABSTOP)) | |||
5161 | { | |||
5162 | aParentTabs.Insert( pParentTabs ); | |||
5163 | } | |||
5164 | } | |||
5165 | ||||
5166 | // #i120938# - consider left indentation of style and its parent style | |||
5167 | long nParentLeft = 0; | |||
5168 | if ( bTabsRelativeToIndex ) | |||
5169 | { | |||
5170 | const SvxLRSpaceItem &rStyleLR = ItemGet<SvxLRSpaceItem>( pParentStyle->GetAttrSet(), RES_LR_SPACE ); | |||
5171 | nParentLeft = rStyleLR.GetTextLeft(); | |||
5172 | } | |||
5173 | ||||
5174 | ParaTabStopDelAdd( m_rWW8Export, aParentTabs, nParentLeft, rTabStops, nCurrentLeft ); | |||
5175 | return; | |||
5176 | } | |||
5177 | ||||
5178 | const SvxTabStopItem* pStyleTabs = nullptr; | |||
5179 | if ( !m_rWW8Export.m_bStyDef && m_rWW8Export.m_pStyAttr ) | |||
5180 | { | |||
5181 | pStyleTabs = m_rWW8Export.m_pStyAttr->GetItem<SvxTabStopItem>(RES_PARATR_TABSTOP); | |||
5182 | } | |||
5183 | ||||
5184 | if ( !pStyleTabs ) | |||
5185 | { | |||
5186 | ParaTabStopAdd(m_rWW8Export, rTabStops, nCurrentLeft); | |||
5187 | } | |||
5188 | else | |||
5189 | { | |||
5190 | long nStyleLeft = 0; | |||
5191 | if ( bTabsRelativeToIndex ) | |||
5192 | { | |||
5193 | const SvxLRSpaceItem &rStyleLR = ItemGet<SvxLRSpaceItem>(*m_rWW8Export.m_pStyAttr, RES_LR_SPACE); | |||
5194 | nStyleLeft = rStyleLR.GetTextLeft(); | |||
5195 | } | |||
5196 | ||||
5197 | ParaTabStopDelAdd( m_rWW8Export, | |||
5198 | *pStyleTabs, nStyleLeft, | |||
5199 | rTabStops, nCurrentLeft); | |||
5200 | } | |||
5201 | } | |||
5202 | ||||
5203 | void AttributeOutputBase::OutputItem( const SfxPoolItem& rHt ) | |||
5204 | { | |||
5205 | // FIXME maybe use 'item_cast', like 'item_cast<SvxCharHiddenItem>( rHt )'? | |||
5206 | switch ( rHt.Which() ) | |||
5207 | { | |||
5208 | case RES_CHRATR_CASEMAP: | |||
5209 | CharCaseMap( static_cast< const SvxCaseMapItem& >( rHt ) ); | |||
5210 | break; | |||
5211 | case RES_CHRATR_COLOR: | |||
5212 | CharColor( static_cast< const SvxColorItem& >( rHt ) ); | |||
5213 | break; | |||
5214 | case RES_CHRATR_CONTOUR: | |||
5215 | CharContour( static_cast< const SvxContourItem& >( rHt ) ); | |||
5216 | break; | |||
5217 | case RES_CHRATR_CROSSEDOUT: | |||
5218 | CharCrossedOut( static_cast< const SvxCrossedOutItem& >( rHt ) ); | |||
5219 | break; | |||
5220 | case RES_CHRATR_ESCAPEMENT: | |||
5221 | CharEscapement( static_cast< const SvxEscapementItem& >( rHt ) ); | |||
5222 | break; | |||
5223 | case RES_CHRATR_FONT: | |||
5224 | CharFont( static_cast< const SvxFontItem& >( rHt ) ); | |||
5225 | break; | |||
5226 | case RES_CHRATR_FONTSIZE: | |||
5227 | CharFontSize( static_cast< const SvxFontHeightItem& >( rHt ) ); | |||
5228 | break; | |||
5229 | case RES_CHRATR_KERNING: | |||
5230 | CharKerning( static_cast< const SvxKerningItem& >( rHt ) ); | |||
5231 | break; | |||
5232 | case RES_CHRATR_LANGUAGE: | |||
5233 | CharLanguage( static_cast< const SvxLanguageItem& >( rHt ) ); | |||
5234 | break; | |||
5235 | case RES_CHRATR_POSTURE: | |||
5236 | CharPosture( static_cast< const SvxPostureItem& >( rHt ) ); | |||
5237 | break; | |||
5238 | case RES_CHRATR_SHADOWED: | |||
5239 | CharShadow( static_cast< const SvxShadowedItem& >( rHt ) ); | |||
5240 | break; | |||
5241 | case RES_CHRATR_UNDERLINE: | |||
5242 | CharUnderline( static_cast< const SvxUnderlineItem& >( rHt ) ); | |||
5243 | break; | |||
5244 | case RES_CHRATR_WEIGHT: | |||
5245 | CharWeight( static_cast< const SvxWeightItem& >( rHt ) ); | |||
5246 | break; | |||
5247 | case RES_CHRATR_AUTOKERN: | |||
5248 | CharAutoKern( static_cast< const SvxAutoKernItem& >( rHt ) ); | |||
5249 | break; | |||
5250 | case RES_CHRATR_BLINK: | |||
5251 | CharAnimatedText( static_cast< const SvxBlinkItem& >( rHt ) ); | |||
5252 | break; | |||
5253 | case RES_CHRATR_BACKGROUND: | |||
5254 | CharBackgroundBase( static_cast< const SvxBrushItem& >( rHt ) ); | |||
5255 | break; | |||
5256 | ||||
5257 | case RES_CHRATR_CJK_FONT: | |||
5258 | CharFontCJK( static_cast< const SvxFontItem& >( rHt ) ); | |||
5259 | break; | |||
5260 | case RES_CHRATR_CJK_FONTSIZE: | |||
5261 | CharFontSizeCJK( static_cast< const SvxFontHeightItem& >( rHt ) ); | |||
5262 | break; | |||
5263 | case RES_CHRATR_CJK_LANGUAGE: | |||
5264 | CharLanguageCJK( static_cast< const SvxLanguageItem& >( rHt ) ); | |||
5265 | break; | |||
5266 | case RES_CHRATR_CJK_POSTURE: | |||
5267 | CharPostureCJK( static_cast< const SvxPostureItem& >( rHt ) ); | |||
5268 | break; | |||
5269 | case RES_CHRATR_CJK_WEIGHT: | |||
5270 | CharWeightCJK( static_cast< const SvxWeightItem& >( rHt ) ); | |||
5271 | break; | |||
5272 | ||||
5273 | case RES_CHRATR_CTL_FONT: | |||
5274 | CharFontCTL( static_cast< const SvxFontItem& >( rHt ) ); | |||
5275 | break; | |||
5276 | case RES_CHRATR_CTL_FONTSIZE: | |||
5277 | CharFontSizeCTL( static_cast< const SvxFontHeightItem& >( rHt ) ); | |||
5278 | break; | |||
5279 | case RES_CHRATR_CTL_LANGUAGE: | |||
5280 | CharLanguageCTL( static_cast< const SvxLanguageItem& >( rHt ) ); | |||
5281 | break; | |||
5282 | case RES_CHRATR_CTL_POSTURE: | |||
5283 | CharPostureCTL( static_cast< const SvxPostureItem& >( rHt ) ); | |||
5284 | break; | |||
5285 | case RES_CHRATR_CTL_WEIGHT: | |||
5286 | CharWeightCTL( static_cast< const SvxWeightItem& >( rHt ) ); | |||
5287 | break; | |||
5288 | ||||
5289 | case RES_CHRATR_ROTATE: | |||
5290 | CharRotate( static_cast< const SvxCharRotateItem& >( rHt ) ); | |||
5291 | break; | |||
5292 | case RES_CHRATR_EMPHASIS_MARK: | |||
5293 | CharEmphasisMark( static_cast< const SvxEmphasisMarkItem& >( rHt ) ); | |||
5294 | break; | |||
5295 | case RES_CHRATR_TWO_LINES: | |||
5296 | CharTwoLines( static_cast< const SvxTwoLinesItem& >( rHt ) ); | |||
5297 | break; | |||
5298 | case RES_CHRATR_SCALEW: | |||
5299 | CharScaleWidth( static_cast< const SvxCharScaleWidthItem& >( rHt ) ); | |||
5300 | break; | |||
5301 | case RES_CHRATR_RELIEF: | |||
5302 | CharRelief( static_cast< const SvxCharReliefItem& >( rHt ) ); | |||
5303 | break; | |||
5304 | case RES_CHRATR_HIDDEN: | |||
5305 | CharHidden( static_cast< const SvxCharHiddenItem& >( rHt ) ); | |||
5306 | break; | |||
5307 | case RES_CHRATR_BOX: | |||
5308 | FormatCharBorder( static_cast< const SvxBoxItem& >( rHt ) ); | |||
5309 | break; | |||
5310 | case RES_CHRATR_HIGHLIGHT: | |||
5311 | CharHighlight( static_cast< const SvxBrushItem& >( rHt ) ); | |||
5312 | break; | |||
5313 | case RES_CHRATR_BIDIRTL: | |||
5314 | CharBidiRTL( rHt ); | |||
5315 | break; | |||
5316 | case RES_CHRATR_IDCTHINT: | |||
5317 | CharIdctHint( rHt ); | |||
5318 | break; | |||
5319 | case RES_TXTATR_INETFMT: | |||
5320 | TextINetFormat( static_cast< const SwFormatINetFormat& >( rHt ) ); | |||
5321 | break; | |||
5322 | case RES_TXTATR_CHARFMT: | |||
5323 | TextCharFormat( static_cast< const SwFormatCharFormat& >( rHt ) ); | |||
5324 | break; | |||
5325 | ||||
5326 | case RES_TXTATR_FIELD: | |||
5327 | case RES_TXTATR_ANNOTATION: | |||
5328 | case RES_TXTATR_INPUTFIELD: | |||
5329 | TextField( static_cast< const SwFormatField& >( rHt ) ); | |||
5330 | break; | |||
5331 | ||||
5332 | case RES_TXTATR_FLYCNT: | |||
5333 | TextFlyContent( static_cast< const SwFormatFlyCnt& >( rHt ) ); | |||
5334 | break; | |||
5335 | case RES_TXTATR_FTN: | |||
5336 | TextFootnote( static_cast< const SwFormatFootnote& >( rHt ) ); | |||
5337 | break; | |||
5338 | ||||
5339 | case RES_PARATR_LINESPACING: | |||
5340 | ParaLineSpacing( static_cast< const SvxLineSpacingItem& >( rHt ) ); | |||
5341 | break; | |||
5342 | case RES_PARATR_ADJUST: | |||
5343 | ParaAdjust( static_cast< const SvxAdjustItem& >( rHt ) ); | |||
5344 | break; | |||
5345 | case RES_PARATR_SPLIT: | |||
5346 | ParaSplit( static_cast< const SvxFormatSplitItem& >( rHt ) ); | |||
5347 | break; | |||
5348 | case RES_PARATR_WIDOWS: | |||
5349 | ParaWidows( static_cast< const SvxWidowsItem& >( rHt ) ); | |||
5350 | break; | |||
5351 | case RES_PARATR_TABSTOP: | |||
5352 | ParaTabStop( static_cast< const SvxTabStopItem& >( rHt ) ); | |||
5353 | break; | |||
5354 | case RES_PARATR_HYPHENZONE: | |||
5355 | ParaHyphenZone( static_cast< const SvxHyphenZoneItem& >( rHt ) ); | |||
5356 | break; | |||
5357 | case RES_PARATR_NUMRULE: | |||
5358 | ParaNumRule( static_cast< const SwNumRuleItem& >( rHt ) ); | |||
5359 | break; | |||
5360 | case RES_PARATR_SCRIPTSPACE: | |||
5361 | ParaScriptSpace( static_cast< const SfxBoolItem& >( rHt ) ); | |||
5362 | break; | |||
5363 | case RES_PARATR_HANGINGPUNCTUATION: | |||
5364 | ParaHangingPunctuation( static_cast< const SfxBoolItem& >( rHt ) ); | |||
5365 | break; | |||
5366 | case RES_PARATR_FORBIDDEN_RULES: | |||
5367 | ParaForbiddenRules( static_cast< const SfxBoolItem& >( rHt ) ); | |||
5368 | break; | |||
5369 | case RES_PARATR_VERTALIGN: | |||
5370 | ParaVerticalAlign( static_cast< const SvxParaVertAlignItem& >( rHt ) ); | |||
5371 | break; | |||
5372 | case RES_PARATR_SNAPTOGRID: | |||
5373 | ParaSnapToGrid( static_cast< const SvxParaGridItem& >( rHt ) ); | |||
5374 | break; | |||
5375 | ||||
5376 | case RES_FRM_SIZE: | |||
5377 | FormatFrameSize( static_cast< const SwFormatFrameSize& >( rHt ) ); | |||
5378 | break; | |||
5379 | case RES_PAPER_BIN: | |||
5380 | FormatPaperBin( static_cast< const SvxPaperBinItem& >( rHt ) ); | |||
5381 | break; | |||
5382 | case RES_LR_SPACE: | |||
5383 | FormatLRSpace( static_cast< const SvxLRSpaceItem& >( rHt ) ); | |||
5384 | break; | |||
5385 | case RES_UL_SPACE: | |||
5386 | FormatULSpace( static_cast< const SvxULSpaceItem& >( rHt ) ); | |||
5387 | break; | |||
5388 | case RES_PAGEDESC: | |||
5389 | FormatPageDescription( static_cast< const SwFormatPageDesc& >( rHt ) ); | |||
5390 | break; | |||
5391 | case RES_BREAK: | |||
5392 | FormatBreak( static_cast< const SvxFormatBreakItem& >( rHt ) ); | |||
5393 | break; | |||
5394 | case RES_SURROUND: | |||
5395 | FormatSurround( static_cast< const SwFormatSurround& >( rHt ) ); | |||
5396 | break; | |||
5397 | case RES_VERT_ORIENT: | |||
5398 | FormatVertOrientation( static_cast< const SwFormatVertOrient& >( rHt ) ); | |||
5399 | break; | |||
5400 | case RES_HORI_ORIENT: | |||
5401 | FormatHorizOrientation( static_cast< const SwFormatHoriOrient& >( rHt ) ); | |||
5402 | break; | |||
5403 | case RES_ANCHOR: | |||
5404 | FormatAnchor( static_cast< const SwFormatAnchor& >( rHt ) ); | |||
5405 | break; | |||
5406 | case RES_BACKGROUND: | |||
5407 | FormatBackground( static_cast< const SvxBrushItem& >( rHt ) ); | |||
5408 | break; | |||
5409 | case XATTR_FILLSTYLE: | |||
5410 | FormatFillStyle( static_cast< const XFillStyleItem& >( rHt ) ); | |||
5411 | break; | |||
5412 | case XATTR_FILLGRADIENT: | |||
5413 | FormatFillGradient( static_cast< const XFillGradientItem& >( rHt ) ); | |||
5414 | break; | |||
5415 | case RES_BOX: | |||
5416 | FormatBox( static_cast< const SvxBoxItem& >( rHt ) ); | |||
5417 | break; | |||
5418 | case RES_COL: | |||
5419 | FormatColumns( static_cast< const SwFormatCol& >( rHt ) ); | |||
5420 | break; | |||
5421 | case RES_KEEP: | |||
5422 | FormatKeep( static_cast< const SvxFormatKeepItem& >( rHt ) ); | |||
5423 | break; | |||
5424 | case RES_TEXTGRID: | |||
5425 | FormatTextGrid( static_cast< const SwTextGridItem& >( rHt ) ); | |||
5426 | break; | |||
5427 | case RES_LINENUMBER: | |||
5428 | FormatLineNumbering( static_cast< const SwFormatLineNumber& >( rHt ) ); | |||
5429 | break; | |||
5430 | case RES_FRAMEDIR: | |||
5431 | FormatFrameDirection( static_cast< const SvxFrameDirectionItem& >( rHt ) ); | |||
5432 | break; | |||
5433 | case RES_PARATR_GRABBAG: | |||
5434 | ParaGrabBag(static_cast<const SfxGrabBagItem&>(rHt)); | |||
5435 | break; | |||
5436 | case RES_PARATR_OUTLINELEVEL: | |||
5437 | ParaOutlineLevel(static_cast<const SfxUInt16Item&>(rHt)); | |||
5438 | break; | |||
5439 | case RES_CHRATR_GRABBAG: | |||
5440 | CharGrabBag(static_cast<const SfxGrabBagItem&>(rHt)); | |||
5441 | break; | |||
5442 | ||||
5443 | default: | |||
5444 | SAL_INFO("sw.ww8", "Unhandled SfxPoolItem with id " << rHt.Which() )do { if (true) { switch (sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_INFO , "sw.ww8")) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail::getResult ( ::sal::detail::StreamStart() << "Unhandled SfxPoolItem with id " << rHt.Which()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "5444" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Unhandled SfxPoolItem with id " << rHt.Which()), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "Unhandled SfxPoolItem with id " << rHt.Which(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "5444" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL : if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart () << "Unhandled SfxPoolItem with id " << rHt.Which ()) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_INFO), ( "sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "5444" ": "), ::sal::detail::unwrapStream( ::sal::detail ::StreamStart() << "Unhandled SfxPoolItem with id " << rHt.Which()), 0); } else { ::std::ostringstream sal_detail_stream ; sal_detail_stream << "Unhandled SfxPoolItem with id " << rHt.Which(); ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_INFO ), ("sw.ww8"), ("/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" ":" "5444" ": "), sal_detail_stream, 0); }; std::abort(); break ; } } } while (false); | |||
5445 | break; | |||
5446 | } | |||
5447 | } | |||
5448 | ||||
5449 | void AttributeOutputBase::OutputStyleItemSet( const SfxItemSet& rSet, bool bTestForDefault ) | |||
5450 | { | |||
5451 | // based on OutputItemSet() from wrt_fn.cxx | |||
5452 | ||||
5453 | const SfxItemPool& rPool = *rSet.GetPool(); | |||
5454 | const SfxItemSet* pSet = &rSet; | |||
5455 | if ( !pSet->Count() ) | |||
5456 | { | |||
5457 | while ( nullptr != ( pSet = pSet->GetParent() ) && !pSet->Count() ) | |||
5458 | ; | |||
5459 | ||||
5460 | if ( !pSet ) | |||
5461 | return; | |||
5462 | } | |||
5463 | ||||
5464 | const SfxPoolItem* pItem; | |||
5465 | if ( !pSet->GetParent() ) | |||
5466 | { | |||
5467 | assert(rSet.Count() && "Was already handled or?")(static_cast <bool> (rSet.Count() && "Was already handled or?" ) ? void (0) : __assert_fail ("rSet.Count() && \"Was already handled or?\"" , "/home/maarten/src/libreoffice/core/sw/source/filter/ww8/ww8atr.cxx" , 5467, __extension__ __PRETTY_FUNCTION__)); | |||
5468 | SfxItemIter aIter( *pSet ); | |||
5469 | pItem = aIter.GetCurItem(); | |||
5470 | do { | |||
5471 | OutputItem( *pItem ); | |||
5472 | } while ((pItem = aIter.NextItem())); | |||
5473 | } | |||
5474 | else | |||
5475 | { | |||
5476 | SfxWhichIter aIter( *pSet ); | |||
5477 | sal_uInt16 nWhich = aIter.FirstWhich(); | |||
5478 | while ( nWhich ) | |||
5479 | { | |||
5480 | if ( SfxItemState::SET == pSet->GetItemState( nWhich, true/*bDeep*/, &pItem ) && | |||
5481 | ( !bTestForDefault || | |||
5482 | nWhich == RES_UL_SPACE || | |||
5483 | nWhich == RES_LR_SPACE || | |||
5484 | *pItem != rPool.GetDefaultItem( nWhich ) || | |||
5485 | ( pSet->GetParent() && *pItem != pSet->GetParent()->Get( nWhich ) ) ) ) | |||
5486 | { | |||
5487 | OutputItem( *pItem ); | |||
5488 | } | |||
5489 | nWhich = aIter.NextWhich(); | |||
5490 | } | |||
5491 | } | |||
5492 | } | |||
5493 | ||||
5494 | void AttributeOutputBase::FormatCharBorder( const SvxBoxItem& rBox ) | |||
5495 | { | |||
5496 | // Get one of the borders (if there is any border then in docx also will be) | |||
5497 | const SvxBorderLine* pBorderLine = nullptr; | |||
5498 | sal_uInt16 nDist = 0; | |||
5499 | if( rBox.GetTop() ) | |||
5500 | { | |||
5501 | pBorderLine = rBox.GetTop(); | |||
5502 | nDist = rBox.GetDistance( SvxBoxItemLine::TOP ); | |||
5503 | } | |||
5504 | else if( rBox.GetLeft() ) | |||
5505 | { | |||
5506 | pBorderLine = rBox.GetLeft(); | |||
5507 | nDist = rBox.GetDistance( SvxBoxItemLine::LEFT ); | |||
5508 | } | |||
5509 | else if( rBox.GetBottom() ) | |||
5510 | { | |||
5511 | pBorderLine = rBox.GetBottom(); | |||
5512 | nDist = rBox.GetDistance( SvxBoxItemLine::BOTTOM ); | |||
5513 | } | |||
5514 | else if( rBox.GetRight() ) | |||
5515 | { | |||
5516 | pBorderLine = rBox.GetRight(); | |||
5517 | nDist = rBox.GetDistance( SvxBoxItemLine::RIGHT ); | |||
5518 | } | |||
5519 | ||||
5520 | // RTF: avoid regressions since RTF doesn't know how to export a border_NONE style-override | |||
5521 | if( pBorderLine || GetExport().GetExportFormat() != MSWordExportBase::ExportFormat::RTF ) | |||
5522 | { | |||
5523 | const SfxPoolItem* pItem = GetExport().HasItem( RES_CHRATR_SHADOW ); | |||
5524 | const SvxShadowItem* pShadowItem = static_cast<const SvxShadowItem*>(pItem); | |||
5525 | const bool bShadow = pBorderLine && | |||
5526 | pShadowItem && pShadowItem->GetLocation() != SvxShadowLocation::NONE && | |||
5527 | pShadowItem->GetWidth() > 0; | |||
5528 | ||||
5529 | CharBorder( pBorderLine, nDist, bShadow ); | |||
5530 | } | |||
5531 | } | |||
5532 | ||||
5533 | /* | |||
5534 | * This function is used to check if the current SwTextNode (paragraph) has a redline object | |||
5535 | * that is attached to the paragraph marker. | |||
5536 | * This is done by checking if the range (SwPaM) of the redline is : | |||
5537 | * - Start = the last character of the current paragraph | |||
5538 | * - End = the first character of the next paragraph | |||
5539 | */ | |||
5540 | const SwRedlineData* AttributeOutputBase::GetParagraphMarkerRedline( const SwTextNode& rNode, RedlineType aRedlineType) | |||
5541 | { | |||
5542 | // ToDo : this is not the most ideal ... should start maybe from 'nCurRedlinePos' | |||
5543 | for(SwRangeRedline* pRedl : GetExport().m_rDoc.getIDocumentRedlineAccess().GetRedlineTable()) | |||
5544 | { | |||
5545 | // Only check redlines that are of type 'Delete' | |||
5546 | if ( pRedl->GetRedlineData().GetType() != aRedlineType ) | |||
5547 | continue; | |||
5548 | ||||
5549 | sal_uLong uStartNodeIndex = pRedl->Start()->nNode.GetIndex(); | |||
5550 | sal_uLong uEndNodeIndex = pRedl->End()->nNode.GetIndex(); | |||
5551 | sal_uLong uNodeIndex = rNode.GetIndex(); | |||
5552 | ||||
5553 | if( uStartNodeIndex <= uNodeIndex && uNodeIndex < uEndNodeIndex ) | |||
5554 | return &( pRedl->GetRedlineData() ); | |||
5555 | } | |||
5556 | return nullptr; | |||
5557 | } | |||
5558 | ||||
5559 | void AttributeOutputBase::CharBackgroundBase( const SvxBrushItem& rBrush ) | |||
5560 | { | |||
5561 | bool bConvertToShading = SvtFilterOptions::Get().IsCharBackground2Shading(); | |||
5562 | bool bHasShadingMarker = false; | |||
5563 | ||||
5564 | // Check shading marker | |||
5565 | const SfxPoolItem* pItem = GetExport().HasItem(RES_CHRATR_GRABBAG); | |||
5566 | if( pItem ) | |||
5567 | { | |||
5568 | const SfxGrabBagItem aGrabBag = static_cast< const SfxGrabBagItem& >(*pItem); | |||
5569 | const std::map<OUString, css::uno::Any>& rMap = aGrabBag.GetGrabBag(); | |||
5570 | auto aIterator = rMap.find("CharShadingMarker"); | |||
5571 | if( aIterator != rMap.end() ) | |||
5572 | { | |||
5573 | aIterator->second >>= bHasShadingMarker; | |||
5574 | } | |||
5575 | } | |||
5576 | ||||
5577 | if( bConvertToShading || bHasShadingMarker ) | |||
5578 | { | |||
5579 | CharBackground(rBrush); | |||
5580 | } | |||
5581 | else | |||
5582 | { | |||
5583 | CharHighlight(rBrush); | |||
5584 | } | |||
5585 | } | |||
5586 | ||||
5587 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |