Line data Source code
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 <ctype.h>
21 : #include <hintids.hxx>
22 : #include <hints.hxx>
23 : #include <vcl/graphicfilter.hxx>
24 :
25 : #include <vcl/graph.hxx>
26 : #include <svl/urihelper.hxx>
27 : #include <editeng/boxitem.hxx>
28 : #include <editeng/wghtitem.hxx>
29 : #include <editeng/cmapitem.hxx>
30 : #include <editeng/contouritem.hxx>
31 : #include <editeng/postitem.hxx>
32 : #include <editeng/crossedoutitem.hxx>
33 : #include <svl/stritem.hxx>
34 : #include <unotools/charclass.hxx>
35 : #include <txtftn.hxx>
36 : #include <fmtpdsc.hxx>
37 : #include <fmtftn.hxx>
38 : #include <fmtanchr.hxx>
39 : #include <fmtrfmrk.hxx>
40 : #include <fmtclds.hxx>
41 : #include <fmtfld.hxx>
42 : #include <fmtfsize.hxx>
43 : #include <fmthdft.hxx>
44 : #include <fmtcntnt.hxx>
45 : #include <redline.hxx>
46 : #include <pam.hxx>
47 : #include <doc.hxx>
48 : #include <IDocumentFieldsAccess.hxx>
49 : #include <IDocumentRedlineAccess.hxx>
50 : #include <IDocumentStylePoolAccess.hxx>
51 : #include <IDocumentState.hxx>
52 : #include <IDocumentLayoutAccess.hxx>
53 : #include <ndtxt.hxx>
54 : #include <frmatr.hxx>
55 : #include <fldbas.hxx>
56 : #include <charatr.hxx>
57 : #include <swtable.hxx>
58 : #include <tox.hxx>
59 : #include <expfld.hxx>
60 : #include <section.hxx>
61 : #include <tblsel.hxx>
62 : #include <pagedesc.hxx>
63 : #include <docsh.hxx>
64 : #include <fltshell.hxx>
65 : #include <viewsh.hxx>
66 : #include <shellres.hxx>
67 :
68 : using namespace com::sun::star;
69 :
70 27155 : static SwContentNode* GetContentNode(SwDoc* pDoc, SwNodeIndex& rIdx, bool bNext)
71 : {
72 27155 : SwContentNode * pCNd = rIdx.GetNode().GetContentNode();
73 27155 : if(!pCNd && 0 == (pCNd = bNext ? pDoc->GetNodes().GoNext(&rIdx)
74 : : SwNodes::GoPrevious(&rIdx)))
75 : {
76 : pCNd = bNext ? SwNodes::GoPrevious(&rIdx)
77 0 : : pDoc->GetNodes().GoNext(&rIdx);
78 : OSL_ENSURE(pCNd, "no ContentNode found");
79 : }
80 27155 : return pCNd;
81 : }
82 :
83 : // Stack entry for all text attributes
84 26208 : SwFltStackEntry::SwFltStackEntry(const SwPosition& rStartPos, SfxPoolItem* pHt)
85 : : m_aMkPos(rStartPos)
86 : , m_aPtPos(rStartPos)
87 : , mnStartCP(-1)
88 : , mnEndCP(-1)
89 26208 : , bIsParaEnd(false)
90 : {
91 26208 : pAttr = pHt; // store a copy of the attribute
92 26208 : bOld = false; // used for marking Attributes *before* skipping field results
93 26208 : bOpen = true; // lock the attribute --> may first
94 26208 : bConsumedByField = false;
95 26208 : }
96 :
97 52416 : SwFltStackEntry::~SwFltStackEntry()
98 : {
99 : // Although attribute got passed as pointer, it gets deleted here
100 26208 : delete pAttr;
101 26208 : }
102 :
103 26486 : void SwFltStackEntry::SetEndPos(const SwPosition& rEndPos)
104 : {
105 : // Release attribute and keep track of end
106 : // Everything with sal_uInt16s, lest the inserting of new text at
107 : // the cursor position moves the attribute's range
108 : // That's not the desired behavior!
109 26486 : bOpen = false; // release and remember END
110 26486 : m_aPtPos.SetPos(rEndPos);
111 26486 : }
112 :
113 24641 : bool SwFltStackEntry::MakeRegion(SwDoc* pDoc, SwPaM& rRegion, bool bCheck,
114 : const SwFltPosition &rMkPos, const SwFltPosition &rPtPos, bool bIsParaEnd,
115 : sal_uInt16 nWhich)
116 : {
117 : // does this range actually contain something?
118 : // empty range is allowed if at start of empty paragraph
119 : // fields are special: never have range, so leave them
120 :
121 : // The only position of 0x0D will not be able to make region in the old logic
122 : // because it is beyond the length of para...need special consideration here.
123 : SwContentNode *const pContentNode(
124 24641 : SwNodeIndex(rMkPos.m_nNode, +1).GetNode().GetContentNode());
125 55180 : if (rMkPos == rPtPos &&
126 10769 : ((0 != rPtPos.m_nContent) || (pContentNode && (0 != pContentNode->Len())))
127 3575 : && ( RES_TXTATR_FIELD != nWhich
128 3575 : && RES_TXTATR_ANNOTATION != nWhich
129 3575 : && RES_TXTATR_INPUTFIELD != nWhich )
130 28216 : && !(bIsParaEnd && pContentNode && pContentNode->IsTextNode() && 0 != pContentNode->Len() ))
131 : {
132 3429 : return false;
133 : }
134 : // The content indices always apply to the node!
135 21212 : rRegion.GetPoint()->nNode = rMkPos.m_nNode.GetIndex() + 1;
136 21212 : SwContentNode* pCNd = GetContentNode(pDoc, rRegion.GetPoint()->nNode, true);
137 21212 : rRegion.GetPoint()->nContent.Assign(pCNd, rMkPos.m_nContent);
138 21212 : rRegion.SetMark();
139 21212 : if (rMkPos.m_nNode != rPtPos.m_nNode)
140 : {
141 5805 : rRegion.GetPoint()->nNode = rPtPos.m_nNode.GetIndex() + 1;
142 5805 : pCNd = GetContentNode(pDoc, rRegion.GetPoint()->nNode, false);
143 : }
144 21212 : rRegion.GetPoint()->nContent.Assign(pCNd, rPtPos.m_nContent);
145 : OSL_ENSURE( CheckNodesRange( rRegion.Start()->nNode,
146 : rRegion.End()->nNode, true ),
147 : "atttribute or similar crosses section-boundaries" );
148 21212 : if( bCheck )
149 36 : return CheckNodesRange( rRegion.Start()->nNode,
150 72 : rRegion.End()->nNode, true );
151 : else
152 21176 : return true;
153 : }
154 :
155 24633 : bool SwFltStackEntry::MakeRegion(SwDoc* pDoc, SwPaM& rRegion, bool bCheck) const
156 : {
157 : return MakeRegion(pDoc, rRegion, bCheck, m_aMkPos, m_aPtPos, bIsParaEnd,
158 24633 : pAttr->Which());
159 : }
160 :
161 1032 : SwFltControlStack::SwFltControlStack(SwDoc* pDo, sal_uLong nFieldFl)
162 1032 : : nFieldFlags(nFieldFl),bHasSdOD(true), bSdODChecked(false), pDoc(pDo), bIsEndStack(false)
163 : {
164 1032 : }
165 :
166 1032 : SwFltControlStack::~SwFltControlStack()
167 : {
168 : OSL_ENSURE(maEntries.empty(), "There are still Attributes on the stack");
169 1032 : }
170 :
171 : // MoveAttrs() is meant to address the following problem:
172 : // When a field like "set variable" is set through the stack, the text
173 : // is shifted by one \xff character, which makes all subsequent
174 : // attribute positions invalid.
175 : // After setting the attribute in the doc, MoveAttrs() needs to be
176 : // called in order to push all attribute positions to the right in the
177 : // same paragraph further out by one character.
178 29 : void SwFltControlStack::MoveAttrs( const SwPosition& rPos )
179 : {
180 29 : size_t nCnt = maEntries.size();
181 29 : sal_uLong nPosNd = rPos.nNode.GetIndex();
182 29 : sal_uInt16 nPosCt = rPos.nContent.GetIndex() - 1;
183 :
184 96 : for (size_t i=0; i < nCnt; ++i)
185 : {
186 67 : SwFltStackEntry& rEntry = maEntries[i];
187 67 : if (
188 109 : (rEntry.m_aMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
189 42 : (rEntry.m_aMkPos.m_nContent >= nPosCt)
190 : )
191 : {
192 5 : rEntry.m_aMkPos.m_nContent++;
193 : OSL_ENSURE( rEntry.m_aMkPos.m_nContent
194 : <= pDoc->GetNodes()[nPosNd]->GetContentNode()->Len(),
195 : "Attribute ends after end of line" );
196 : }
197 67 : if (
198 115 : (rEntry.m_aPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
199 48 : (rEntry.m_aPtPos.m_nContent >= nPosCt)
200 : )
201 : {
202 25 : rEntry.m_aPtPos.m_nContent++;
203 : OSL_ENSURE( rEntry.m_aPtPos.m_nContent
204 : <= pDoc->GetNodes()[nPosNd]->GetContentNode()->Len(),
205 : "Attribute ends after end of line" );
206 : }
207 : }
208 29 : }
209 :
210 53 : void SwFltControlStack::MarkAllAttrsOld()
211 : {
212 53 : size_t nCnt = maEntries.size();
213 453 : for (size_t i=0; i < nCnt; ++i)
214 400 : maEntries[i].bOld = true;
215 53 : }
216 :
217 : namespace
218 : {
219 26985 : bool couldExtendEntry(const SwFltStackEntry *pExtendCandidate,
220 : const SfxPoolItem& rAttr)
221 : {
222 2977 : return (pExtendCandidate &&
223 5954 : !pExtendCandidate->bConsumedByField &&
224 : //potentially more, but lets keep it simple
225 34528 : (isPARATR_LIST(rAttr.Which()) || (isCHRATR(rAttr.Which()) && rAttr.Which() != RES_CHRATR_FONT && rAttr.Which() != RES_CHRATR_FONTSIZE)) &&
226 28574 : *(pExtendCandidate->pAttr) == rAttr);
227 : }
228 : }
229 :
230 26985 : void SwFltControlStack::NewAttr(const SwPosition& rPos, const SfxPoolItem& rAttr)
231 : {
232 26985 : sal_uInt16 nWhich = rAttr.Which();
233 : // Set end position of potentially equal attributes on stack, so
234 : // as to avoid having them accumulate
235 26985 : SwFltStackEntry *pExtendCandidate = SetAttr(rPos, nWhich);
236 26985 : if (couldExtendEntry(pExtendCandidate, rAttr))
237 : {
238 : //Here we optimize by seeing if there is an attribute uncommited
239 : //to the document which
240 :
241 : //a) has the same value as this attribute
242 : //b) is already open, or ends at the same place as where we're starting
243 : //from. If so we merge it with this one and elide adding another
244 : //to the stack
245 782 : pExtendCandidate->SetEndPos(rPos);
246 782 : pExtendCandidate->bOpen=true;
247 : }
248 : else
249 : {
250 26203 : SwFltStackEntry *pTmp = new SwFltStackEntry(rPos, rAttr.Clone() );
251 26203 : pTmp->SetStartCP(GetCurrAttrCP());
252 26203 : maEntries.push_back(pTmp);
253 : }
254 26985 : }
255 :
256 1565 : void SwFltControlStack::DeleteAndDestroy(Entries::size_type nCnt)
257 : {
258 : OSL_ENSURE(nCnt < maEntries.size(), "Out of range!");
259 1565 : if (nCnt < maEntries.size())
260 : {
261 1565 : myEIter aElement = maEntries.begin() + nCnt;
262 1565 : maEntries.erase(aElement);
263 : }
264 : //Clear the para end position recorded in reader intermittently for the least impact on loading performance
265 : //Because the attributes handled based on the unit of para
266 1565 : if ( empty() )
267 : {
268 223 : ClearParaEndPosition();
269 223 : bHasSdOD = true;
270 223 : bSdODChecked = false;
271 : }
272 1565 : }
273 :
274 : // SwFltControlStack::StealAttr() removes attributes of the given type
275 : // from the stack. Allowed as nAttrId: 0 meaning any, or a specific
276 : // type. This makes them disappear from the doc structure. Only
277 : // attributes from the same paragraph as rPos are removed. Used for
278 : // graphic apos -> images.
279 0 : void SwFltControlStack::StealAttr(const SwNodeIndex& rNode, sal_uInt16 nAttrId)
280 : {
281 0 : size_t nCnt = maEntries.size();
282 :
283 0 : while (nCnt)
284 : {
285 0 : nCnt --;
286 0 : SwFltStackEntry& rEntry = maEntries[nCnt];
287 0 : if (rEntry.m_aPtPos.m_nNode.GetIndex()+1 == rNode.GetIndex() &&
288 0 : (!nAttrId || nAttrId == rEntry.pAttr->Which()))
289 : {
290 0 : DeleteAndDestroy(nCnt); // loesche aus dem Stack
291 : }
292 : }
293 0 : }
294 :
295 : // SwFltControlStack::KillUnlockedAttr() removes all attributes from
296 : // the stack, which are assigned to an rPos. This makes them disappear
297 : // from the doc structure. Used in WW import for ignoring attributes
298 : // assigned to the 0x0c section break symbol.
299 115 : void SwFltControlStack::KillUnlockedAttrs(const SwPosition& rPos)
300 : {
301 115 : SwFltPosition aFltPos(rPos);
302 :
303 115 : size_t nCnt = maEntries.size();
304 1112 : while( nCnt )
305 : {
306 882 : nCnt --;
307 882 : SwFltStackEntry& rEntry = maEntries[nCnt];
308 1764 : if( !rEntry.bOld
309 479 : && !rEntry.bOpen
310 299 : && (rEntry.m_aMkPos == aFltPos)
311 1124 : && (rEntry.m_aPtPos == aFltPos))
312 : {
313 242 : DeleteAndDestroy( nCnt ); // remove from stack
314 : }
315 115 : }
316 115 : }
317 :
318 : // Unlock all locked attributes and move to the end, all others will
319 : // be applied to the document and removed from the stack.
320 : // Returns if there were any selected attributes on the stack
321 53072 : SwFltStackEntry* SwFltControlStack::SetAttr(const SwPosition& rPos,
322 : sal_uInt16 nAttrId, bool bTstEnde, long nHand,
323 : bool consumedByField)
324 : {
325 53072 : SwFltStackEntry *pRet = NULL;
326 :
327 53072 : SwFltPosition aFltPos(rPos);
328 :
329 : OSL_ENSURE(!nAttrId ||
330 : (POOLATTR_BEGIN <= nAttrId && POOLATTR_END > nAttrId) ||
331 : (RES_FLTRATTR_BEGIN <= nAttrId && RES_FLTRATTR_END > nAttrId),
332 : "Wrong id for attribute");
333 :
334 53072 : myEIter aI = maEntries.begin();
335 1564335 : while (aI != maEntries.end())
336 : {
337 1458191 : bool bLastEntry = aI == maEntries.end() - 1;
338 :
339 1458191 : SwFltStackEntry& rEntry = *aI;
340 1458191 : if (rEntry.bOpen)
341 : {
342 : // set end of attribute
343 236314 : bool bF = false;
344 236314 : if (!nAttrId )
345 : {
346 53 : bF = true;
347 : }
348 236261 : else if (nAttrId == rEntry.pAttr->Which())
349 : {
350 25662 : if( nAttrId != RES_FLTR_BOOKMARK && nAttrId != RES_FLTR_ANNOTATIONMARK )
351 : {
352 : // query handle
353 25586 : bF = true;
354 : }
355 76 : else if (nAttrId == RES_FLTR_BOOKMARK && nHand == static_cast<SwFltBookmark*>(rEntry.pAttr)->GetHandle())
356 : {
357 40 : bF = true;
358 : }
359 36 : else if (nAttrId == RES_FLTR_ANNOTATIONMARK && nHand == static_cast<CntUInt16Item*>(rEntry.pAttr)->GetValue())
360 : {
361 20 : bF = true;
362 : }
363 : }
364 236314 : if (bF)
365 : {
366 25699 : rEntry.bConsumedByField = consumedByField;
367 25699 : rEntry.SetEndPos(rPos);
368 25699 : rEntry.SetEndCP(GetCurrAttrCP());
369 25699 : if (bLastEntry && nAttrId == rEntry.pAttr->Which())
370 : {
371 : //potential candidate for merging with an identical
372 : //property beginning at rPos
373 7328 : pRet = &rEntry;
374 : }
375 : }
376 236314 : ++aI;
377 236314 : continue;
378 : }
379 :
380 : // if the end position is equal to the cursor position, then
381 : // refrain from applying it; there needs to be following text,
382 : // except at the very end. (attribute expansion !!)
383 : // Never apply end stack except at document ending
384 1221877 : if (bTstEnde)
385 : {
386 1219923 : if (bIsEndStack)
387 : {
388 238 : ++aI;
389 238 : continue;
390 : }
391 :
392 : //defer inserting this attribute into the document until
393 : //we advance to the next node, or finish processing the document
394 1219685 : if (rEntry.m_aPtPos.m_nNode.GetIndex() == aFltPos.m_nNode.GetIndex())
395 : {
396 1199828 : if (bLastEntry && nAttrId == rEntry.pAttr->Which() &&
397 2827 : rEntry.m_aPtPos.m_nContent == aFltPos.m_nContent)
398 : {
399 : //potential candidate for merging with an identical
400 : //property beginning at rPos
401 2797 : pRet = &rEntry;
402 : }
403 :
404 1197001 : ++aI;
405 1197001 : continue;
406 : }
407 : }
408 24638 : SetAttrInDoc(rPos, rEntry);
409 24638 : aI = maEntries.erase(aI);
410 : }
411 :
412 53072 : return pRet;
413 : }
414 :
415 138 : static void MakePoint(const SwFltStackEntry& rEntry, SwDoc* pDoc,
416 : SwPaM& rRegion)
417 : {
418 : // the anchor is the Pam's Point. It's modified when inserting
419 : // text, etc.; therefore it is kept on the stack. Only the
420 : // attribute's format needs to be set.
421 138 : rRegion.DeleteMark();
422 138 : rRegion.GetPoint()->nNode = rEntry.m_aMkPos.m_nNode.GetIndex() + 1;
423 138 : SwContentNode* pCNd = GetContentNode(pDoc, rRegion.GetPoint()->nNode, true);
424 138 : rRegion.GetPoint()->nContent.Assign(pCNd, rEntry.m_aMkPos.m_nContent);
425 138 : }
426 :
427 : // MakeBookRegionOrPoint() behaves like MakeRegionOrPoint, except that
428 : // it adheres to certain restrictions on bookmarks in tables (cannot
429 : // span more than one cell)
430 55 : static void MakeBookRegionOrPoint(const SwFltStackEntry& rEntry, SwDoc* pDoc,
431 : SwPaM& rRegion, bool bCheck )
432 : {
433 55 : if (rEntry.MakeRegion(pDoc, rRegion, bCheck )){
434 : // sal_Bool b1 = rNds[rRegion.GetPoint()->nNode]->FindTableNode() != 0;
435 62 : if (rRegion.GetPoint()->nNode.GetNode().FindTableBoxStartNode()
436 31 : != rRegion.GetMark()->nNode.GetNode().FindTableBoxStartNode())
437 : {
438 0 : rRegion.Exchange(); // invalid range
439 0 : rRegion.DeleteMark(); // -> both to mark
440 : }
441 : }else{
442 24 : MakePoint(rEntry, pDoc, rRegion);
443 : }
444 55 : }
445 :
446 : // IterateNumrulePiece() looks for the first range valid for Numrules
447 : // between rTmpStart and rEnd.
448 :
449 : // rNds denotes the doc nodes
450 : // rEnd denotes the range end,
451 : // rTmpStart is an in/out parameter: in: start of range to be searched,
452 : // out: start of valid range
453 : // rTmpEnd is an out parameter
454 : // Returns true for valid range
455 0 : static bool IterateNumrulePiece( const SwNodeIndex& rEnd,
456 : SwNodeIndex& rTmpStart, SwNodeIndex& rTmpEnd )
457 : {
458 0 : while( ( rTmpStart <= rEnd )
459 0 : && !( rTmpStart.GetNode().IsTextNode() ) ) // look for valid start
460 0 : ++rTmpStart;
461 :
462 0 : rTmpEnd = rTmpStart;
463 0 : while( ( rTmpEnd <= rEnd )
464 0 : && ( rTmpEnd.GetNode().IsTextNode() ) ) // look for valid end + 1
465 0 : ++rTmpEnd;
466 :
467 0 : --rTmpEnd; // valid end
468 :
469 0 : return rTmpStart <= rTmpEnd; // valid ?
470 : }
471 :
472 : //***This function will check whether there is existing individual attribute position for 0x0D***/
473 : //The check will happen only once for a paragraph during loading
474 174 : bool SwFltControlStack::HasSdOD()
475 : {
476 174 : bool bRet = false;
477 :
478 1410 : for (Entries::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
479 : {
480 1257 : SwFltStackEntry& rEntry = *it;
481 1257 : if ( rEntry.mnStartCP == rEntry.mnEndCP )
482 : {
483 221 : if ( CheckSdOD(rEntry.mnStartCP,rEntry.mnEndCP) )
484 : {
485 21 : bRet = true;
486 21 : break;
487 : }
488 : }
489 : }
490 :
491 174 : return bRet;
492 : }
493 :
494 23069 : void SwFltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
495 : SwFltStackEntry& rEntry)
496 : {
497 23069 : SwPaM aRegion( rTmpPos );
498 :
499 23069 : switch(rEntry.pAttr->Which())
500 : {
501 : case RES_FLTR_ANCHOR:
502 : {
503 114 : SwFrameFormat* pFormat = static_cast<SwFltAnchor*>(rEntry.pAttr)->GetFrameFormat();
504 114 : if (pFormat != NULL)
505 : {
506 114 : MakePoint(rEntry, pDoc, aRegion);
507 114 : SwFormatAnchor aAnchor(pFormat->GetAnchor());
508 114 : aAnchor.SetAnchor(aRegion.GetPoint());
509 114 : pFormat->SetFormatAttr(aAnchor);
510 : // So the frames will be created when inserting into
511 : // existing doc (after setting the anchor!):
512 228 : if(pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()
513 114 : && (FLY_AT_PARA == pFormat->GetAnchor().GetAnchorId()))
514 : {
515 0 : pFormat->MakeFrms();
516 114 : }
517 : }
518 : }
519 114 : break;
520 :
521 : case RES_TXTATR_FIELD:
522 : case RES_TXTATR_ANNOTATION:
523 : case RES_TXTATR_INPUTFIELD:
524 0 : break;
525 :
526 : case RES_TXTATR_TOXMARK:
527 0 : break;
528 :
529 : case RES_FLTR_NUMRULE: // insert Numrule
530 : {
531 0 : const OUString& rNumNm = static_cast<SfxStringItem*>(rEntry.pAttr)->GetValue();
532 0 : SwNumRule* pNumRule = pDoc->FindNumRulePtr( rNumNm );
533 0 : if( pNumRule )
534 : {
535 0 : if( rEntry.MakeRegion(pDoc, aRegion, true))
536 : {
537 0 : SwNodeIndex aTmpStart( aRegion.Start()->nNode );
538 0 : SwNodeIndex aTmpEnd( aTmpStart );
539 0 : SwNodeIndex& rRegEndNd = aRegion.End()->nNode;
540 0 : while( IterateNumrulePiece( rRegEndNd,
541 : aTmpStart, aTmpEnd ) )
542 : {
543 0 : SwPaM aTmpPam( aTmpStart, aTmpEnd );
544 : // no start of a new list
545 0 : pDoc->SetNumRule( aTmpPam, *pNumRule, false );
546 :
547 0 : aTmpStart = aTmpEnd; // here starts the next range
548 0 : ++aTmpStart;
549 0 : }
550 : }
551 : else
552 0 : pDoc->DelNumRule( rNumNm );
553 : }
554 : }
555 0 : break;
556 :
557 : case RES_FLTR_BOOKMARK:
558 : {
559 40 : SwFltBookmark* pB = static_cast<SwFltBookmark*>(rEntry.pAttr);
560 40 : const OUString& rName = static_cast<SwFltBookmark*>(rEntry.pAttr)->GetName();
561 :
562 40 : if (IsFlagSet(BOOK_TO_VAR_REF))
563 : {
564 0 : SwFieldType* pFT = pDoc->getIDocumentFieldsAccess().GetFieldType(RES_SETEXPFLD, rName, false);
565 0 : if (!pFT)
566 : {
567 0 : SwSetExpFieldType aS(pDoc, rName, nsSwGetSetExpType::GSE_STRING);
568 0 : pFT = pDoc->getIDocumentFieldsAccess().InsertFieldType(aS);
569 : }
570 0 : SwSetExpField aField(static_cast<SwSetExpFieldType*>(pFT), pB->GetValSys());
571 0 : aField.SetSubType( nsSwExtendedSubType::SUB_INVISIBLE );
572 0 : MakePoint(rEntry, pDoc, aRegion);
573 0 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, SwFormatField(aField));
574 0 : MoveAttrs( *(aRegion.GetPoint()) );
575 : }
576 80 : if ( ( !IsFlagSet(HYPO) || IsFlagSet(BOOK_AND_REF) ) &&
577 40 : !rEntry.bConsumedByField )
578 : {
579 35 : MakeBookRegionOrPoint(rEntry, pDoc, aRegion, true);
580 : // #i120879# - create a cross reference heading bookmark if appropriate.
581 : const IDocumentMarkAccess::MarkType eBookmarkType =
582 40 : ( pB->IsTOCBookmark() &&
583 5 : IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( aRegion ) )
584 : ? IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK
585 40 : : IDocumentMarkAccess::MarkType::BOOKMARK;
586 35 : pDoc->getIDocumentMarkAccess()->makeMark( aRegion, rName, eBookmarkType );
587 : }
588 : }
589 40 : break;
590 : case RES_FLTR_ANNOTATIONMARK:
591 : {
592 20 : MakeBookRegionOrPoint(rEntry, pDoc, aRegion, true);
593 20 : pDoc->getIDocumentMarkAccess()->makeAnnotationMark(aRegion, OUString());
594 : }
595 20 : break;
596 : case RES_FLTR_TOX:
597 : {
598 0 : MakePoint(rEntry, pDoc, aRegion);
599 :
600 0 : SwPosition* pPoint = aRegion.GetPoint();
601 :
602 0 : SwFltTOX* pTOXAttr = static_cast<SwFltTOX*>(rEntry.pAttr);
603 :
604 : // test if on this node there had been a pagebreak BEFORE the
605 : // tox attribute was put on the stack
606 0 : SfxItemSet aBkSet( pDoc->GetAttrPool(), RES_PAGEDESC, RES_BREAK );
607 0 : SwContentNode* pNd = 0;
608 0 : if( !pTOXAttr->HadBreakItem() || !pTOXAttr->HadPageDescItem() )
609 : {
610 0 : pNd = pPoint->nNode.GetNode().GetContentNode();
611 0 : if( pNd )
612 : {
613 0 : const SfxItemSet* pSet = pNd->GetpSwAttrSet();
614 : const SfxPoolItem* pItem;
615 0 : if( pSet )
616 : {
617 0 : if( !pTOXAttr->HadBreakItem()
618 0 : && SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem ) )
619 : {
620 0 : aBkSet.Put( *pItem );
621 0 : pNd->ResetAttr( RES_BREAK );
622 : }
623 0 : if( !pTOXAttr->HadPageDescItem()
624 0 : && SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem ) )
625 : {
626 0 : aBkSet.Put( *pItem );
627 0 : pNd->ResetAttr( RES_PAGEDESC );
628 : }
629 : }
630 : }
631 : }
632 :
633 0 : delete pTOXAttr->GetBase();
634 :
635 : // set (aboved saved and removed) the break item at the node following the TOX
636 0 : if( aBkSet.Count() )
637 0 : pNd->SetAttr( aBkSet );
638 : }
639 0 : break;
640 : case RES_FLTR_REDLINE:
641 : {
642 0 : if (rEntry.MakeRegion(pDoc, aRegion, true))
643 : {
644 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)( nsRedlineMode_t::REDLINE_ON
645 : | nsRedlineMode_t::REDLINE_SHOW_INSERT
646 0 : | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
647 0 : SwFltRedline& rFltRedline = *static_cast<SwFltRedline*>(rEntry.pAttr);
648 :
649 0 : if( USHRT_MAX != rFltRedline.nAutorNoPrev )
650 : {
651 : SwRedlineData aData(rFltRedline.eTypePrev,
652 : rFltRedline.nAutorNoPrev,
653 : rFltRedline.aStampPrev,
654 : OUString(),
655 : 0
656 0 : );
657 0 : pDoc->getIDocumentRedlineAccess().AppendRedline(new SwRangeRedline(aData, aRegion), true);
658 : }
659 : SwRedlineData aData(rFltRedline.eType,
660 : rFltRedline.nAutorNo,
661 : rFltRedline.aStamp,
662 : OUString(),
663 : 0
664 0 : );
665 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline(aData, aRegion), true );
666 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)( nsRedlineMode_t::REDLINE_NONE
667 : | nsRedlineMode_t::REDLINE_SHOW_INSERT
668 0 : | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
669 : }
670 : }
671 0 : break;
672 : default:
673 : {
674 : // Revised for more complex situations should be considered
675 22895 : if ( !bSdODChecked )
676 : {
677 174 : bHasSdOD = HasSdOD();
678 174 : bSdODChecked = true;
679 : }
680 22895 : sal_Int32 nStart = rEntry.GetStartCP();
681 22895 : sal_Int32 nEnd = rEntry.GetEndCP();
682 22895 : if (nStart != -1 && nEnd != -1 && nEnd >= nStart )
683 : {
684 22892 : rEntry.SetIsParaEnd( IsParaEndInCPs(nStart,nEnd,bHasSdOD) );
685 : }
686 22895 : if (rEntry.MakeRegion(pDoc, aRegion, false))
687 : {
688 20059 : if (rEntry.IsParaEnd())
689 : {
690 2995 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, *rEntry.pAttr, SetAttrMode::DEFAULT, true);
691 : }
692 : else
693 : {
694 17064 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, *rEntry.pAttr);
695 : }
696 : }
697 : }
698 22895 : break;
699 23069 : }
700 23069 : }
701 :
702 0 : bool SwFltControlStack::IsParaEndInCPs(sal_Int32 /*nStart*/, sal_Int32 /*nEnd*/,bool /*bSdOD*/) const
703 : {
704 0 : return false;
705 : }
706 :
707 0 : bool SwFltControlStack::CheckSdOD(sal_Int32 /*nStart*/, sal_Int32 /*nEnd*/)
708 : {
709 0 : return false;
710 : }
711 :
712 8 : SfxPoolItem* SwFltControlStack::GetFormatStackAttr(sal_uInt16 nWhich, sal_uInt16 * pPos)
713 : {
714 8 : size_t nSize = maEntries.size();
715 :
716 8 : while (nSize)
717 : {
718 : // is it the looked-for attribute ? (only applies to locked, meaning
719 : // currently set attributes!!)
720 8 : SwFltStackEntry &rEntry = maEntries[--nSize];
721 8 : if (rEntry.bOpen && rEntry.pAttr->Which() == nWhich)
722 : {
723 8 : if (pPos)
724 8 : *pPos = nSize;
725 8 : return rEntry.pAttr; // Ok, so stop
726 : }
727 : }
728 0 : return 0;
729 : }
730 :
731 0 : const SfxPoolItem* SwFltControlStack::GetOpenStackAttr(const SwPosition& rPos, sal_uInt16 nWhich)
732 : {
733 0 : SwFltPosition aFltPos(rPos);
734 :
735 0 : size_t nSize = maEntries.size();
736 :
737 0 : while (nSize)
738 : {
739 0 : SwFltStackEntry &rEntry = maEntries[--nSize];
740 0 : if (rEntry.bOpen && rEntry.pAttr->Which() == nWhich && rEntry.m_aMkPos == aFltPos)
741 : {
742 0 : return rEntry.pAttr;
743 : }
744 : }
745 0 : return 0;
746 : }
747 :
748 1 : void SwFltControlStack::Delete(const SwPaM &rPam)
749 : {
750 1 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
751 :
752 1 : if( !rPam.HasMark() || *pStt >= *pEnd )
753 0 : return;
754 :
755 1 : SwNodeIndex aStartNode(pStt->nNode, -1);
756 1 : const sal_Int32 nStartIdx = pStt->nContent.GetIndex();
757 2 : SwNodeIndex aEndNode(pEnd->nNode, -1);
758 1 : const sal_Int32 nEndIdx = pEnd->nContent.GetIndex();
759 :
760 : // We don't support deleting content that is over one node, or removing a node.
761 : OSL_ENSURE(aEndNode == aStartNode, "nodes must be the same, or this method extended");
762 1 : if (aEndNode != aStartNode)
763 0 : return;
764 :
765 2 : for (size_t nSize = maEntries.size(); nSize > 0;)
766 : {
767 0 : SwFltStackEntry& rEntry = maEntries[--nSize];
768 :
769 : bool bEntryStartAfterSelStart =
770 0 : (rEntry.m_aMkPos.m_nNode == aStartNode &&
771 0 : rEntry.m_aMkPos.m_nContent >= nStartIdx);
772 :
773 : bool bEntryStartBeforeSelEnd =
774 0 : (rEntry.m_aMkPos.m_nNode == aEndNode &&
775 0 : rEntry.m_aMkPos.m_nContent <= nEndIdx);
776 :
777 0 : bool bEntryEndAfterSelStart = false;
778 0 : bool bEntryEndBeforeSelEnd = false;
779 0 : if (!rEntry.bOpen)
780 : {
781 : bEntryEndAfterSelStart =
782 0 : (rEntry.m_aPtPos.m_nNode == aStartNode &&
783 0 : rEntry.m_aPtPos.m_nContent >= nStartIdx);
784 :
785 : bEntryEndBeforeSelEnd =
786 0 : (rEntry.m_aPtPos.m_nNode == aEndNode &&
787 0 : rEntry.m_aPtPos.m_nContent <= nEndIdx);
788 : }
789 :
790 0 : bool bTotallyContained = false;
791 0 : if (
792 0 : bEntryStartAfterSelStart && bEntryStartBeforeSelEnd &&
793 0 : bEntryEndAfterSelStart && bEntryEndBeforeSelEnd
794 : )
795 : {
796 0 : bTotallyContained = true;
797 : }
798 :
799 0 : if (bTotallyContained)
800 : {
801 : // after start, before end, delete
802 0 : DeleteAndDestroy(nSize);
803 0 : continue;
804 : }
805 :
806 0 : const sal_Int32 nContentDiff = nEndIdx - nStartIdx;
807 :
808 : // to be adjusted
809 0 : if (bEntryStartAfterSelStart)
810 : {
811 0 : if (bEntryStartBeforeSelEnd)
812 : {
813 : // move start to new start
814 0 : rEntry.m_aMkPos.SetPos(aStartNode, nStartIdx);
815 : }
816 : else
817 0 : rEntry.m_aMkPos.m_nContent -= nContentDiff;
818 : }
819 :
820 0 : if (bEntryEndAfterSelStart)
821 : {
822 0 : if (bEntryEndBeforeSelEnd)
823 0 : rEntry.m_aPtPos.SetPos(aStartNode, nStartIdx);
824 : else
825 0 : rEntry.m_aPtPos.m_nContent -= nContentDiff;
826 : }
827 :
828 : //That's what Open is, end equal to start, and nPtContent is invalid
829 0 : if (rEntry.bOpen)
830 0 : rEntry.m_aPtPos = rEntry.m_aMkPos;
831 1 : }
832 : }
833 :
834 : // methods of SwFltAnchor follow
835 114 : SwFltAnchor::SwFltAnchor(SwFrameFormat* pFormat) :
836 114 : SfxPoolItem(RES_FLTR_ANCHOR), pFrameFormat(pFormat)
837 : {
838 114 : pClient = new SwFltAnchorClient(this);
839 114 : pFrameFormat->Add(pClient);
840 114 : }
841 :
842 114 : SwFltAnchor::SwFltAnchor(const SwFltAnchor& rCpy) :
843 114 : SfxPoolItem(RES_FLTR_ANCHOR), pFrameFormat(rCpy.pFrameFormat)
844 : {
845 114 : pClient = new SwFltAnchorClient(this);
846 114 : pFrameFormat->Add(pClient);
847 114 : }
848 :
849 570 : SwFltAnchor::~SwFltAnchor()
850 : {
851 228 : delete pClient;
852 342 : }
853 :
854 0 : void SwFltAnchor::SetFrameFormat(SwFrameFormat * _pFrameFormat)
855 : {
856 0 : pFrameFormat = _pFrameFormat;
857 0 : }
858 :
859 :
860 :
861 0 : bool SwFltAnchor::operator==(const SfxPoolItem& rItem) const
862 : {
863 0 : return pFrameFormat == static_cast<const SwFltAnchor&>(rItem).pFrameFormat;
864 : }
865 :
866 114 : SfxPoolItem* SwFltAnchor::Clone(SfxItemPool*) const
867 : {
868 114 : return new SwFltAnchor(*this);
869 : }
870 :
871 228 : SwFltAnchorClient::SwFltAnchorClient(SwFltAnchor * pFltAnchor)
872 228 : : m_pFltAnchor(pFltAnchor)
873 : {
874 228 : }
875 :
876 19 : void SwFltAnchorClient::Modify(const SfxPoolItem *, const SfxPoolItem * pNew)
877 : {
878 19 : if (pNew->Which() == RES_FMT_CHG)
879 : {
880 0 : const SwFormatChg * pFormatChg = dynamic_cast<const SwFormatChg *> (pNew);
881 :
882 0 : if (pFormatChg != NULL)
883 : {
884 0 : SwFrameFormat * pFrameFormat = dynamic_cast<SwFrameFormat *> (pFormatChg->pChangedFormat);
885 :
886 0 : if (pFrameFormat != NULL)
887 0 : m_pFltAnchor->SetFrameFormat(pFrameFormat);
888 : }
889 : }
890 19 : }
891 :
892 : // methods of SwFltRedline follow
893 0 : bool SwFltRedline::operator==(const SfxPoolItem& rItem) const
894 : {
895 0 : return this == &rItem;
896 : }
897 :
898 5 : SfxPoolItem* SwFltRedline::Clone( SfxItemPool* ) const
899 : {
900 5 : return new SwFltRedline(*this);
901 : }
902 :
903 : // methods of SwFltBookmark follow
904 40 : SwFltBookmark::SwFltBookmark( const OUString& rNa, const OUString& rVa,
905 : long nHand, const bool bIsTOCBookmark )
906 : : SfxPoolItem( RES_FLTR_BOOKMARK )
907 : , mnHandle( nHand )
908 : , maName( rNa )
909 : , maVal( rVa )
910 40 : , mbIsTOCBookmark( bIsTOCBookmark )
911 : {
912 : // eSrc: CHARSET_DONTKNOW for no transform at operator <<
913 : // Upcase is always done.
914 : // Transform is never done at XXXStack.NewAttr(...).
915 : // otherwise: Src Charset from argument for aName
916 : // Src Charset from filter for aVal ( Text )
917 :
918 40 : if ( IsTOCBookmark() && ! rNa.startsWith(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()) )
919 : {
920 0 : maName = IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix();
921 0 : maName += rNa;
922 : }
923 40 : }
924 :
925 40 : SwFltBookmark::SwFltBookmark(const SwFltBookmark& rCpy)
926 : : SfxPoolItem( RES_FLTR_BOOKMARK )
927 : , mnHandle( rCpy.mnHandle )
928 : , maName( rCpy.maName )
929 : , maVal( rCpy.maVal )
930 40 : , mbIsTOCBookmark( rCpy.mbIsTOCBookmark )
931 : {
932 40 : }
933 :
934 0 : bool SwFltBookmark::operator==(const SfxPoolItem& rItem) const
935 : {
936 0 : return ( maName == static_cast<const SwFltBookmark&>(rItem).maName)
937 0 : && (mnHandle == static_cast<const SwFltBookmark&>(rItem).mnHandle);
938 : }
939 :
940 40 : SfxPoolItem* SwFltBookmark::Clone(SfxItemPool*) const
941 : {
942 40 : return new SwFltBookmark(*this);
943 : }
944 :
945 : // methods of SwFltTOX follow
946 0 : SwFltTOX::SwFltTOX(SwTOXBase* pBase, sal_uInt16 _nCols)
947 : : SfxPoolItem(RES_FLTR_TOX), pTOXBase(pBase), nCols( _nCols ),
948 0 : bHadBreakItem( false ), bHadPageDescItem( false )
949 : {
950 0 : }
951 :
952 0 : SwFltTOX::SwFltTOX(const SwFltTOX& rCpy)
953 : : SfxPoolItem(RES_FLTR_TOX), pTOXBase(rCpy.pTOXBase), nCols( rCpy.nCols ),
954 0 : bHadBreakItem( rCpy.bHadBreakItem ), bHadPageDescItem( rCpy.bHadPageDescItem )
955 : {
956 0 : }
957 :
958 0 : bool SwFltTOX::operator==(const SfxPoolItem& rItem) const
959 : {
960 0 : return pTOXBase == static_cast<const SwFltTOX&>(rItem).pTOXBase;
961 : }
962 :
963 0 : SfxPoolItem* SwFltTOX::Clone(SfxItemPool*) const
964 : {
965 0 : return new SwFltTOX(*this);
966 : }
967 :
968 : // UpdatePageDescs needs to be called at end of parsing to make Writer actually
969 : // accept Pagedescs contents
970 125 : void UpdatePageDescs(SwDoc &rDoc, size_t nInPageDescOffset)
971 : {
972 : // Update document page descriptors (only this way also left pages
973 : // get adjusted)
974 :
975 : // PageDesc "Standard"
976 125 : rDoc.ChgPageDesc(0, rDoc.GetPageDesc(0));
977 :
978 : // PageDescs "Convert..."
979 143 : for (size_t i = nInPageDescOffset; i < rDoc.GetPageDescCnt(); ++i)
980 18 : rDoc.ChgPageDesc(i, rDoc.GetPageDesc(i));
981 302 : }
982 :
983 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|