File: | home/maarten/src/libreoffice/core/sw/source/filter/ascii/ascatr.cxx |
Warning: | line 335, column 25 Value stored to 'nStrPos' is never read |
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 | #include <hintids.hxx> |
21 | #include <tools/stream.hxx> |
22 | #include <comphelper/string.hxx> |
23 | #include <pam.hxx> |
24 | #include <doc.hxx> |
25 | #include <ndtxt.hxx> |
26 | #include <IDocumentRedlineAccess.hxx> |
27 | #include <redline.hxx> |
28 | #include "wrtasc.hxx" |
29 | #include <txatbase.hxx> |
30 | #include <txtfld.hxx> |
31 | #include <fmtftn.hxx> |
32 | #include <fmtfld.hxx> |
33 | #include <fldbas.hxx> |
34 | #include <ftninfo.hxx> |
35 | #include <numrule.hxx> |
36 | |
37 | #include <algorithm> |
38 | |
39 | /* |
40 | * This file contains all output functions of the ASCII-Writer; |
41 | * For all nodes, attributes, formats and chars. |
42 | */ |
43 | |
44 | namespace { |
45 | |
46 | class SwASC_AttrIter |
47 | { |
48 | SwASCWriter& rWrt; |
49 | const SwTextNode& rNd; |
50 | sal_Int32 nCurrentSwPos; |
51 | |
52 | sal_Int32 SearchNext( sal_Int32 nStartPos ); |
53 | |
54 | public: |
55 | SwASC_AttrIter( SwASCWriter& rWrt, const SwTextNode& rNd, sal_Int32 nStt ); |
56 | |
57 | void NextPos() |
58 | { |
59 | nCurrentSwPos = SearchNext( nCurrentSwPos + 1 ); |
60 | } |
61 | |
62 | sal_Int32 WhereNext() const |
63 | { |
64 | return nCurrentSwPos; |
65 | } |
66 | |
67 | bool OutAttr( sal_Int32 nSwPos ); |
68 | }; |
69 | |
70 | } |
71 | |
72 | SwASC_AttrIter::SwASC_AttrIter( |
73 | SwASCWriter& rWr, |
74 | const SwTextNode& rTextNd, |
75 | sal_Int32 nStt ) |
76 | : rWrt( rWr ) |
77 | , rNd( rTextNd ) |
78 | , nCurrentSwPos( 0 ) |
79 | { |
80 | nCurrentSwPos = SearchNext( nStt + 1 ); |
81 | } |
82 | |
83 | sal_Int32 SwASC_AttrIter::SearchNext( sal_Int32 nStartPos ) |
84 | { |
85 | sal_Int32 nMinPos = SAL_MAX_INT32((sal_Int32) 0x7FFFFFFF); |
86 | const SwpHints* pTextAttrs = rNd.GetpSwpHints(); |
87 | if( pTextAttrs ) |
88 | { |
89 | // TODO: This can be optimized, if we make use of the fact that the TextAttrs |
90 | // are sorted by starting position. We would need to remember two indices, however. |
91 | for ( size_t i = 0; i < pTextAttrs->Count(); ++i ) |
92 | { |
93 | const SwTextAttr* pHt = pTextAttrs->Get(i); |
94 | if ( pHt->HasDummyChar() ) |
95 | { |
96 | sal_Int32 nPos = pHt->GetStart(); |
97 | |
98 | if( nPos >= nStartPos && nPos <= nMinPos ) |
99 | nMinPos = nPos; |
100 | |
101 | if( ( ++nPos ) >= nStartPos && nPos < nMinPos ) |
102 | nMinPos = nPos; |
103 | } |
104 | else if ( pHt->HasContent() ) |
105 | { |
106 | const sal_Int32 nHintStart = pHt->GetStart(); |
107 | if ( nHintStart >= nStartPos && nHintStart <= nMinPos ) |
108 | { |
109 | nMinPos = nHintStart; |
110 | } |
111 | |
112 | const sal_Int32 nHintEnd = pHt->End() ? *pHt->End() : COMPLETE_STRING; |
113 | if ( nHintEnd >= nStartPos && nHintEnd < nMinPos ) |
114 | { |
115 | nMinPos = nHintEnd; |
116 | } |
117 | } |
118 | } |
119 | } |
120 | return nMinPos; |
121 | } |
122 | |
123 | bool SwASC_AttrIter::OutAttr( sal_Int32 nSwPos ) |
124 | { |
125 | bool bRet = false; |
126 | const SwpHints* pTextAttrs = rNd.GetpSwpHints(); |
127 | if( pTextAttrs ) |
128 | { |
129 | for( size_t i = 0; i < pTextAttrs->Count(); ++i ) |
130 | { |
131 | const SwTextAttr* pHt = pTextAttrs->Get(i); |
132 | if ( ( pHt->HasDummyChar() |
133 | || pHt->HasContent() ) |
134 | && nSwPos == pHt->GetStart() ) |
135 | { |
136 | bRet = true; |
137 | OUString sOut; |
138 | switch( pHt->Which() ) |
139 | { |
140 | case RES_TXTATR_FIELD: |
141 | case RES_TXTATR_ANNOTATION: |
142 | case RES_TXTATR_INPUTFIELD: |
143 | sOut = static_txtattr_cast<SwTextField const*>(pHt) |
144 | ->GetFormatField().GetField()->ExpandField(true, nullptr); |
145 | break; |
146 | |
147 | case RES_TXTATR_FTN: |
148 | { |
149 | const SwFormatFootnote& rFootnote = pHt->GetFootnote(); |
150 | if( !rFootnote.GetNumStr().isEmpty() ) |
151 | sOut = rFootnote.GetNumStr(); |
152 | else if( rFootnote.IsEndNote() ) |
153 | sOut = rWrt.m_pDoc->GetEndNoteInfo().m_aFormat. |
154 | GetNumStr( rFootnote.GetNumber() ); |
155 | else |
156 | sOut = rWrt.m_pDoc->GetFootnoteInfo().m_aFormat. |
157 | GetNumStr( rFootnote.GetNumber() ); |
158 | } |
159 | break; |
160 | } |
161 | if( !sOut.isEmpty() ) |
162 | rWrt.Strm().WriteUnicodeOrByteText( sOut ); |
163 | } |
164 | else if( nSwPos < pHt->GetStart() ) |
165 | break; |
166 | } |
167 | } |
168 | return bRet; |
169 | } |
170 | |
171 | namespace { |
172 | |
173 | class SwASC_RedlineIter |
174 | { |
175 | private: |
176 | SwTextNode const& m_rNode; |
177 | IDocumentRedlineAccess const& m_rIDRA; |
178 | SwRedlineTable::size_type m_nextRedline; |
179 | |
180 | public: |
181 | SwASC_RedlineIter(SwASCWriter const& rWriter, SwTextNode const& rNode) |
182 | : m_rNode(rNode) |
183 | , m_rIDRA(rNode.GetDoc().getIDocumentRedlineAccess()) |
184 | , m_nextRedline(rWriter.m_bHideDeleteRedlines |
185 | ? m_rIDRA.GetRedlinePos(m_rNode, RedlineType::Delete) |
186 | : SwRedlineTable::npos) |
187 | { |
188 | } |
189 | |
190 | bool CheckNodeDeleted() |
191 | { |
192 | if (m_nextRedline == SwRedlineTable::npos) |
193 | { |
194 | return false; |
195 | } |
196 | SwRangeRedline const*const pRedline(m_rIDRA.GetRedlineTable()[m_nextRedline]); |
197 | return pRedline->Start()->nNode.GetIndex() < m_rNode.GetIndex() |
198 | && m_rNode.GetIndex() < pRedline->End()->nNode.GetIndex(); |
199 | } |
200 | |
201 | std::pair<sal_Int32, sal_Int32> GetNextRedlineSkip() |
202 | { |
203 | sal_Int32 nRedlineStart(COMPLETE_STRING); |
204 | sal_Int32 nRedlineEnd(COMPLETE_STRING); |
205 | for ( ; m_nextRedline < m_rIDRA.GetRedlineTable().size(); ++m_nextRedline) |
206 | { |
207 | SwRangeRedline const*const pRedline(m_rIDRA.GetRedlineTable()[m_nextRedline]); |
208 | if (pRedline->GetType() != RedlineType::Delete) |
209 | { |
210 | continue; |
211 | } |
212 | SwPosition const*const pStart(pRedline->Start()); |
213 | SwPosition const*const pEnd(pRedline->End()); |
214 | if (m_rNode.GetIndex() < pStart->nNode.GetIndex()) |
215 | { |
216 | m_nextRedline = SwRedlineTable::npos; |
217 | break; // done |
218 | } |
219 | if (nRedlineStart == COMPLETE_STRING) |
220 | { |
221 | nRedlineStart = pStart->nNode.GetIndex() == m_rNode.GetIndex() |
222 | ? pStart->nContent.GetIndex() |
223 | : 0; |
224 | } |
225 | else |
226 | { |
227 | if (pStart->nContent.GetIndex() != nRedlineEnd) |
228 | { |
229 | assert(nRedlineEnd < pStart->nContent.GetIndex())(static_cast <bool> (nRedlineEnd < pStart->nContent .GetIndex()) ? void (0) : __assert_fail ("nRedlineEnd < pStart->nContent.GetIndex()" , "/home/maarten/src/libreoffice/core/sw/source/filter/ascii/ascatr.cxx" , 229, __extension__ __PRETTY_FUNCTION__)); |
230 | break; // no increment, revisit it next call |
231 | } |
232 | } |
233 | nRedlineEnd = pEnd->nNode.GetIndex() == m_rNode.GetIndex() |
234 | ? pEnd->nContent.GetIndex() |
235 | : COMPLETE_STRING; |
236 | } |
237 | return std::make_pair(nRedlineStart, nRedlineEnd); |
238 | } |
239 | }; |
240 | |
241 | } |
242 | |
243 | // Output of the node |
244 | |
245 | static Writer& OutASC_SwTextNode( Writer& rWrt, SwContentNode& rNode ) |
246 | { |
247 | const SwTextNode& rNd = static_cast<SwTextNode&>(rNode); |
248 | |
249 | sal_Int32 nStrPos = rWrt.m_pCurrentPam->GetPoint()->nContent.GetIndex(); |
250 | const sal_Int32 nNodeEnd = rNd.Len(); |
251 | sal_Int32 nEnd = nNodeEnd; |
252 | bool bLastNd = rWrt.m_pCurrentPam->GetPoint()->nNode == rWrt.m_pCurrentPam->GetMark()->nNode; |
253 | if( bLastNd ) |
254 | nEnd = rWrt.m_pCurrentPam->GetMark()->nContent.GetIndex(); |
255 | |
256 | bool bIsOneParagraph = rWrt.m_pOrigPam->Start()->nNode == rWrt.m_pOrigPam->End()->nNode; |
257 | |
258 | SwASC_AttrIter aAttrIter( static_cast<SwASCWriter&>(rWrt), rNd, nStrPos ); |
259 | SwASC_RedlineIter redlineIter(static_cast<SwASCWriter&>(rWrt), rNd); |
260 | |
261 | if (redlineIter.CheckNodeDeleted()) |
262 | { |
263 | return rWrt; |
264 | } |
265 | |
266 | const SwNumRule* pNumRule = rNd.GetNumRule(); |
267 | if (pNumRule && !nStrPos && rWrt.m_bExportParagraphNumbering && !bIsOneParagraph) |
268 | { |
269 | bool bIsOutlineNumRule = pNumRule == rNd.GetDoc().GetOutlineNumRule(); |
270 | |
271 | // indent each numbering level by 4 spaces |
272 | OUString level; |
273 | if (!bIsOutlineNumRule) |
274 | { |
275 | for (int i = 0; i <= rNd.GetActualListLevel(); ++i) |
276 | level += " "; |
277 | } |
278 | |
279 | // set up bullets or numbering |
280 | OUString numString(rNd.GetNumString()); |
281 | if (numString.isEmpty() && !bIsOutlineNumRule) |
282 | { |
283 | if (rNd.HasBullet() && !rNd.HasVisibleNumberingOrBullet()) |
284 | numString = " "; |
285 | else if (rNd.HasBullet()) |
286 | numString = OUString(numfunc::GetBulletChar(rNd.GetActualListLevel())); |
287 | else if (!rNd.HasBullet() && !rNd.HasVisibleNumberingOrBullet()) |
288 | numString = " "; |
289 | } |
290 | |
291 | if (!level.isEmpty() || !numString.isEmpty()) |
292 | rWrt.Strm().WriteUnicodeOrByteText(level + numString + " "); |
293 | } |
294 | |
295 | OUString aStr( rNd.GetText() ); |
296 | if( rWrt.m_bASCII_ParaAsBlank ) |
297 | aStr = aStr.replace(0x0A, ' '); |
298 | |
299 | const bool bExportSoftHyphens = RTL_TEXTENCODING_UCS2(((rtl_TextEncoding) 0xFFFF)) == rWrt.GetAsciiOptions().GetCharSet() || |
300 | RTL_TEXTENCODING_UTF8(((rtl_TextEncoding) 76)) == rWrt.GetAsciiOptions().GetCharSet(); |
301 | |
302 | std::pair<sal_Int32, sal_Int32> curRedline(redlineIter.GetNextRedlineSkip()); |
303 | for (;;) { |
304 | const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd); |
305 | |
306 | bool isOutAttr(false); |
307 | if (nStrPos < curRedline.first || curRedline.second <= nStrPos) |
308 | { |
309 | isOutAttr = aAttrIter.OutAttr(nStrPos); |
310 | } |
311 | |
312 | if (!isOutAttr) |
313 | { |
314 | OUStringBuffer buf; |
315 | while (true) |
316 | { |
317 | if (nNextAttr <= curRedline.first) |
318 | { |
319 | buf.append(aStr.copy(nStrPos, nNextAttr - nStrPos)); |
320 | break; |
321 | } |
322 | else if (nStrPos < curRedline.second) |
323 | { |
324 | if (nStrPos < curRedline.first) |
325 | { |
326 | buf.append(aStr.copy(nStrPos, curRedline.first - nStrPos)); |
327 | } |
328 | if (curRedline.second <= nNextAttr) |
329 | { |
330 | nStrPos = curRedline.second; |
331 | curRedline = redlineIter.GetNextRedlineSkip(); |
332 | } |
333 | else |
334 | { |
335 | nStrPos = nNextAttr; |
Value stored to 'nStrPos' is never read | |
336 | break; |
337 | } |
338 | } |
339 | else |
340 | { |
341 | curRedline = redlineIter.GetNextRedlineSkip(); |
342 | } |
343 | } |
344 | OUString aOutStr(buf.makeStringAndClear()); |
345 | if ( !bExportSoftHyphens ) |
346 | aOutStr = aOutStr.replaceAll(OUStringChar(CHAR_SOFTHYPHENu'\x00AD'), ""); |
347 | |
348 | // all INWORD/BREAKWORD should be already removed by OutAttr |
349 | // but the field-marks are not attributes so filter those |
350 | static sal_Unicode const forbidden [] = { |
351 | CH_TXT_ATR_INPUTFIELDSTARTu'\x0004', |
352 | CH_TXT_ATR_INPUTFIELDENDu'\x0005', |
353 | CH_TXT_ATR_FORMELEMENTu'\x0006', |
354 | CH_TXT_ATR_FIELDSTARTu'\x0007', |
355 | CH_TXT_ATR_FIELDSEPu'\x0003', |
356 | CH_TXT_ATR_FIELDENDu'\x0008', |
357 | 0 |
358 | }; |
359 | aOutStr = comphelper::string::removeAny(aOutStr, forbidden); |
360 | |
361 | rWrt.Strm().WriteUnicodeOrByteText( aOutStr ); |
362 | } |
363 | nStrPos = nNextAttr; |
364 | if (nStrPos >= nEnd) |
365 | { |
366 | break; |
367 | } |
368 | aAttrIter.NextPos(); |
369 | } |
370 | |
371 | if( !bLastNd || |
372 | ( ( !rWrt.m_bWriteClipboardDoc && !rWrt.m_bASCII_NoLastLineEnd ) |
373 | && !nStrPos && nEnd == nNodeEnd ) ) |
374 | rWrt.Strm().WriteUnicodeOrByteText( static_cast<SwASCWriter&>(rWrt).GetLineEnd()); |
375 | |
376 | return rWrt; |
377 | } |
378 | |
379 | /* |
380 | * Create the table for the ASCII function pointers to the output |
381 | * function. |
382 | * There are local structures that only need to be known to the ASCII DLL. |
383 | */ |
384 | |
385 | SwNodeFnTab aASCNodeFnTab = { |
386 | /* RES_TXTNODE */ OutASC_SwTextNode, |
387 | /* RES_GRFNODE */ nullptr, |
388 | /* RES_OLENODE */ nullptr |
389 | }; |
390 | |
391 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |