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 53484 : static SwCntntNode* GetCntntNode(SwDoc* pDoc, SwNodeIndex& rIdx, bool bNext)
71 : {
72 53484 : SwCntntNode * pCNd = rIdx.GetNode().GetCntntNode();
73 53678 : if(!pCNd && 0 == (pCNd = bNext ? pDoc->GetNodes().GoNext(&rIdx)
74 194 : : pDoc->GetNodes().GoPrevious(&rIdx)))
75 : {
76 0 : pCNd = bNext ? pDoc->GetNodes().GoPrevious(&rIdx)
77 0 : : pDoc->GetNodes().GoNext(&rIdx);
78 : OSL_ENSURE(pCNd, "no ContentNode found");
79 : }
80 53484 : return pCNd;
81 : }
82 :
83 : // Stack entry for all text attributes
84 51084 : SwFltStackEntry::SwFltStackEntry(const SwPosition& rStartPos, SfxPoolItem* pHt)
85 : : m_aMkPos(rStartPos)
86 : , m_aPtPos(rStartPos)
87 : , mnStartCP(-1)
88 : , mnEndCP(-1)
89 51084 : , bIsParaEnd(false)
90 : {
91 51084 : pAttr = pHt; // store a copy of the attribute
92 51084 : bOld = false; // used for marking Attributes *before* skipping field results
93 51084 : bOpen = true; // lock the attribute --> may first
94 51084 : bConsumedByField = false;
95 51084 : }
96 :
97 102168 : SwFltStackEntry::~SwFltStackEntry()
98 : {
99 : // Although attribute got passed as pointer, it gets deleted here
100 51084 : delete pAttr;
101 51084 : }
102 :
103 52192 : 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 52192 : bOpen = false; // release and remember END
110 52192 : m_aPtPos.SetPos(rEndPos);
111 52192 : }
112 :
113 48574 : 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 : SwCntntNode *const pCntntNode(
124 48574 : SwNodeIndex(rMkPos.m_nNode, +1).GetNode().GetCntntNode());
125 108822 : if (rMkPos == rPtPos &&
126 21304 : ((0 != rPtPos.m_nCntnt) || (pCntntNode && (0 != pCntntNode->Len())))
127 7078 : && ( RES_TXTATR_FIELD != nWhich
128 7078 : && RES_TXTATR_ANNOTATION != nWhich
129 7078 : && RES_TXTATR_INPUTFIELD != nWhich )
130 55652 : && !(bIsParaEnd && pCntntNode && pCntntNode->IsTxtNode() && 0 != pCntntNode->Len() ))
131 : {
132 6792 : return false;
133 : }
134 : // The content indices always apply to the node!
135 41782 : rRegion.GetPoint()->nNode = rMkPos.m_nNode.GetIndex() + 1;
136 41782 : SwCntntNode* pCNd = GetCntntNode(pDoc, rRegion.GetPoint()->nNode, true);
137 41782 : rRegion.GetPoint()->nContent.Assign(pCNd, rMkPos.m_nCntnt);
138 41782 : rRegion.SetMark();
139 41782 : if (rMkPos.m_nNode != rPtPos.m_nNode)
140 : {
141 11486 : rRegion.GetPoint()->nNode = rPtPos.m_nNode.GetIndex() + 1;
142 11486 : pCNd = GetCntntNode(pDoc, rRegion.GetPoint()->nNode, false);
143 : }
144 41782 : rRegion.GetPoint()->nContent.Assign(pCNd, rPtPos.m_nCntnt);
145 : OSL_ENSURE( CheckNodesRange( rRegion.Start()->nNode,
146 : rRegion.End()->nNode, true ),
147 : "atttribute or similar crosses section-boundaries" );
148 41782 : if( bCheck )
149 32 : return CheckNodesRange( rRegion.Start()->nNode,
150 64 : rRegion.End()->nNode, true );
151 : else
152 41750 : return true;
153 : }
154 :
155 48558 : bool SwFltStackEntry::MakeRegion(SwDoc* pDoc, SwPaM& rRegion, bool bCheck) const
156 : {
157 : return MakeRegion(pDoc, rRegion, bCheck, m_aMkPos, m_aPtPos, bIsParaEnd,
158 48558 : pAttr->Which());
159 : }
160 :
161 1744 : SwFltControlStack::SwFltControlStack(SwDoc* pDo, sal_uLong nFieldFl)
162 1744 : : nFieldFlags(nFieldFl),bHasSdOD(true), bSdODChecked(false), pDoc(pDo), bIsEndStack(false)
163 : {
164 1744 : }
165 :
166 1744 : SwFltControlStack::~SwFltControlStack()
167 : {
168 : OSL_ENSURE(maEntries.empty(), "There are still Attributes on the stack");
169 1744 : }
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 0 : void SwFltControlStack::MoveAttrs( const SwPosition& rPos )
179 : {
180 0 : size_t nCnt = maEntries.size();
181 0 : sal_uLong nPosNd = rPos.nNode.GetIndex();
182 0 : sal_uInt16 nPosCt = rPos.nContent.GetIndex() - 1;
183 :
184 0 : for (size_t i=0; i < nCnt; ++i)
185 : {
186 0 : SwFltStackEntry& rEntry = maEntries[i];
187 0 : if (
188 0 : (rEntry.m_aMkPos.m_nNode.GetIndex()+1 == nPosNd) &&
189 0 : (rEntry.m_aMkPos.m_nCntnt >= nPosCt)
190 : )
191 : {
192 0 : rEntry.m_aMkPos.m_nCntnt++;
193 : OSL_ENSURE( rEntry.m_aMkPos.m_nCntnt
194 : <= pDoc->GetNodes()[nPosNd]->GetCntntNode()->Len(),
195 : "Attribute ends after end of line" );
196 : }
197 0 : if (
198 0 : (rEntry.m_aPtPos.m_nNode.GetIndex()+1 == nPosNd) &&
199 0 : (rEntry.m_aPtPos.m_nCntnt >= nPosCt)
200 : )
201 : {
202 0 : rEntry.m_aPtPos.m_nCntnt++;
203 : OSL_ENSURE( rEntry.m_aPtPos.m_nCntnt
204 : <= pDoc->GetNodes()[nPosNd]->GetCntntNode()->Len(),
205 : "Attribute ends after end of line" );
206 : }
207 : }
208 0 : }
209 :
210 68 : void SwFltControlStack::MarkAllAttrsOld()
211 : {
212 68 : size_t nCnt = maEntries.size();
213 790 : for (sal_uInt16 i=0; i < nCnt; ++i)
214 722 : maEntries[i].bOld = true;
215 68 : }
216 :
217 : namespace
218 : {
219 52614 : bool couldExtendEntry(const SwFltStackEntry *pExtendCandidate,
220 : const SfxPoolItem& rAttr)
221 : {
222 5824 : return (pExtendCandidate &&
223 11648 : !pExtendCandidate->bConsumedByField &&
224 : //potentially more, but lets keep it simple
225 67368 : (isPARATR_LIST(rAttr.Which()) || (isCHRATR(rAttr.Which()) && rAttr.Which() != RES_CHRATR_FONT && rAttr.Which() != RES_CHRATR_FONTSIZE)) &&
226 55720 : *(pExtendCandidate->pAttr) == rAttr);
227 : }
228 : }
229 :
230 52614 : void SwFltControlStack::NewAttr(const SwPosition& rPos, const SfxPoolItem& rAttr)
231 : {
232 52614 : sal_uInt16 nWhich = rAttr.Which();
233 : // Set end position of potentially equal attributes on stack, so
234 : // as to avoid having them accumulate
235 52614 : SwFltStackEntry *pExtendCandidate = SetAttr(rPos, nWhich);
236 52614 : 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 1540 : pExtendCandidate->SetEndPos(rPos);
246 1540 : pExtendCandidate->bOpen=true;
247 : }
248 : else
249 : {
250 51074 : SwFltStackEntry *pTmp = new SwFltStackEntry(rPos, rAttr.Clone() );
251 51074 : pTmp->SetStartCP(GetCurrAttrCP());
252 51074 : maEntries.push_back(pTmp);
253 : }
254 52614 : }
255 :
256 2522 : void SwFltControlStack::DeleteAndDestroy(Entries::size_type nCnt)
257 : {
258 : OSL_ENSURE(nCnt < maEntries.size(), "Out of range!");
259 2522 : if (nCnt < maEntries.size())
260 : {
261 2522 : myEIter aElement = maEntries.begin() + nCnt;
262 2522 : 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 2522 : if ( empty() )
267 : {
268 402 : ClearParaEndPosition();
269 402 : bHasSdOD = true;
270 402 : bSdODChecked = false;
271 : }
272 2522 : }
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 192 : void SwFltControlStack::KillUnlockedAttrs(const SwPosition& rPos)
300 : {
301 192 : SwFltPosition aFltPos(rPos);
302 :
303 192 : size_t nCnt = maEntries.size();
304 2064 : while( nCnt )
305 : {
306 1680 : nCnt --;
307 1680 : SwFltStackEntry& rEntry = maEntries[nCnt];
308 3360 : if( !rEntry.bOld
309 958 : && !rEntry.bOpen
310 598 : && (rEntry.m_aMkPos == aFltPos)
311 2164 : && (rEntry.m_aPtPos == aFltPos))
312 : {
313 484 : DeleteAndDestroy( nCnt ); // remove from stack
314 : }
315 192 : }
316 192 : }
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 104102 : SwFltStackEntry* SwFltControlStack::SetAttr(const SwPosition& rPos,
322 : sal_uInt16 nAttrId, bool bTstEnde, long nHand,
323 : bool consumedByField)
324 : {
325 104102 : SwFltStackEntry *pRet = NULL;
326 :
327 104102 : 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 104102 : myEIter aI = maEntries.begin();
335 3092860 : while (aI != maEntries.end())
336 : {
337 2884656 : bool bLastEntry = aI == maEntries.end() - 1;
338 :
339 2884656 : SwFltStackEntry& rEntry = *aI;
340 2884656 : if (rEntry.bOpen)
341 : {
342 : // set end of attribute
343 450368 : bool bF = false;
344 450368 : if (!nAttrId )
345 : {
346 46 : bF = true;
347 : }
348 450322 : else if (nAttrId == rEntry.pAttr->Which())
349 : {
350 50600 : if( nAttrId != RES_FLTR_BOOKMARK )
351 : {
352 : // query handle
353 50548 : bF = true;
354 : }
355 52 : else if (nHand == ((SwFltBookmark*)(rEntry.pAttr))->GetHandle())
356 : {
357 48 : bF = true;
358 : }
359 : }
360 450368 : if (bF)
361 : {
362 50642 : rEntry.bConsumedByField = consumedByField;
363 50642 : rEntry.SetEndPos(rPos);
364 50642 : rEntry.SetEndCP(GetCurrAttrCP());
365 50642 : if (bLastEntry && nAttrId == rEntry.pAttr->Which())
366 : {
367 : //potential candidate for merging with an identical
368 : //property beginning at rPos
369 14280 : pRet = &rEntry;
370 : }
371 : }
372 450368 : ++aI;
373 450368 : continue;
374 : }
375 :
376 : // if the end position is equal to the cursor position, then
377 : // refrain from applying it; there needs to be following text,
378 : // except at the very end. (attribute expansion !!)
379 : // Never apply end stack except at document ending
380 2434288 : if (bTstEnde)
381 : {
382 2430834 : if (bIsEndStack)
383 : {
384 166 : ++aI;
385 166 : continue;
386 : }
387 :
388 : //defer inserting this attribute into the document until
389 : //we advance to the next node, or finish processing the document
390 2430668 : if (rEntry.m_aPtPos.m_nNode.GetIndex() == aFltPos.m_nNode.GetIndex())
391 : {
392 2391090 : if (bLastEntry && nAttrId == rEntry.pAttr->Which() &&
393 5520 : rEntry.m_aPtPos.m_nCntnt == aFltPos.m_nCntnt)
394 : {
395 : //potential candidate for merging with an identical
396 : //property beginning at rPos
397 5470 : pRet = &rEntry;
398 : }
399 :
400 2385570 : ++aI;
401 2385570 : continue;
402 : }
403 : }
404 48552 : SetAttrInDoc(rPos, rEntry);
405 48552 : aI = maEntries.erase(aI);
406 : }
407 :
408 104102 : return pRet;
409 : }
410 :
411 216 : static void MakePoint(const SwFltStackEntry& rEntry, SwDoc* pDoc,
412 : SwPaM& rRegion)
413 : {
414 : // the anchor is the Pam's Point. It's modified when inserting
415 : // text, etc.; therefore it is kept on the stack. Only the
416 : // attribute's format needs to be set.
417 216 : rRegion.DeleteMark();
418 216 : rRegion.GetPoint()->nNode = rEntry.m_aMkPos.m_nNode.GetIndex() + 1;
419 216 : SwCntntNode* pCNd = GetCntntNode(pDoc, rRegion.GetPoint()->nNode, true);
420 216 : rRegion.GetPoint()->nContent.Assign(pCNd, rEntry.m_aMkPos.m_nCntnt);
421 216 : }
422 :
423 : // MakeBookRegionOrPoint() behaves like MakeRegionOrPoint, except that
424 : // it adheres to certain restrictions on bookmarks in tables (cannot
425 : // span more than one cell)
426 44 : static void MakeBookRegionOrPoint(const SwFltStackEntry& rEntry, SwDoc* pDoc,
427 : SwPaM& rRegion, bool bCheck )
428 : {
429 44 : if (rEntry.MakeRegion(pDoc, rRegion, bCheck )){
430 : // sal_Bool b1 = rNds[rRegion.GetPoint()->nNode]->FindTableNode() != 0;
431 44 : if (rRegion.GetPoint()->nNode.GetNode().FindTableBoxStartNode()
432 22 : != rRegion.GetMark()->nNode.GetNode().FindTableBoxStartNode())
433 : {
434 0 : rRegion.Exchange(); // invalid range
435 0 : rRegion.DeleteMark(); // -> both to mark
436 : }
437 : }else{
438 22 : MakePoint(rEntry, pDoc, rRegion);
439 : }
440 44 : }
441 :
442 : // IterateNumrulePiece() looks for the first range valid for Numrules
443 : // between rTmpStart and rEnd.
444 :
445 : // rNds denotes the doc nodes
446 : // rEnd denotes the range end,
447 : // rTmpStart is an in/out parameter: in: start of range to be searched,
448 : // out: start of valid range
449 : // rTmpEnd is an out parameter
450 : // Returns true for valid range
451 0 : static bool IterateNumrulePiece( const SwNodeIndex& rEnd,
452 : SwNodeIndex& rTmpStart, SwNodeIndex& rTmpEnd )
453 : {
454 0 : while( ( rTmpStart <= rEnd )
455 0 : && !( rTmpStart.GetNode().IsTxtNode() ) ) // look for valid start
456 0 : ++rTmpStart;
457 :
458 0 : rTmpEnd = rTmpStart;
459 0 : while( ( rTmpEnd <= rEnd )
460 0 : && ( rTmpEnd.GetNode().IsTxtNode() ) ) // look for valid end + 1
461 0 : ++rTmpEnd;
462 :
463 0 : rTmpEnd--; // valid end
464 :
465 0 : return rTmpStart <= rTmpEnd; // valid ?
466 : }
467 :
468 : //***This function will check whether there is existing individual attribute position for 0x0D***/
469 : //The check will happen only once for a paragraph during loading
470 312 : bool SwFltControlStack::HasSdOD()
471 : {
472 312 : bool bRet = false;
473 :
474 2432 : for (Entries::iterator it = maEntries.begin(); it != maEntries.end(); ++it)
475 : {
476 2162 : SwFltStackEntry& rEntry = *it;
477 2162 : if ( rEntry.mnStartCP == rEntry.mnEndCP )
478 : {
479 412 : if ( CheckSdOD(rEntry.mnStartCP,rEntry.mnEndCP) )
480 : {
481 42 : bRet = true;
482 42 : break;
483 : }
484 : }
485 : }
486 :
487 312 : return bRet;
488 : }
489 :
490 45390 : void SwFltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
491 : SwFltStackEntry& rEntry)
492 : {
493 45390 : SwPaM aRegion( rTmpPos );
494 :
495 45390 : switch(rEntry.pAttr->Which())
496 : {
497 : case RES_FLTR_ANCHOR:
498 : {
499 194 : SwFrmFmt* pFmt = ((SwFltAnchor*)rEntry.pAttr)->GetFrmFmt();
500 194 : if (pFmt != NULL)
501 : {
502 194 : MakePoint(rEntry, pDoc, aRegion);
503 194 : SwFmtAnchor aAnchor(pFmt->GetAnchor());
504 194 : aAnchor.SetAnchor(aRegion.GetPoint());
505 194 : pFmt->SetFmtAttr(aAnchor);
506 : // So the frames will be created when inserting into
507 : // existing doc (after setting the anchor!):
508 388 : if(pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()
509 194 : && (FLY_AT_PARA == pFmt->GetAnchor().GetAnchorId()))
510 : {
511 0 : pFmt->MakeFrms();
512 194 : }
513 : }
514 : }
515 194 : break;
516 :
517 : case RES_TXTATR_FIELD:
518 : case RES_TXTATR_ANNOTATION:
519 : case RES_TXTATR_INPUTFIELD:
520 0 : break;
521 :
522 : case RES_TXTATR_TOXMARK:
523 0 : break;
524 :
525 : case RES_FLTR_NUMRULE: // insert Numrule
526 : {
527 0 : const OUString& rNumNm = ((SfxStringItem*)rEntry.pAttr)->GetValue();
528 0 : SwNumRule* pNumRule = pDoc->FindNumRulePtr( rNumNm );
529 0 : if( pNumRule )
530 : {
531 0 : if( rEntry.MakeRegion(pDoc, aRegion, true))
532 : {
533 0 : SwNodeIndex aTmpStart( aRegion.Start()->nNode );
534 0 : SwNodeIndex aTmpEnd( aTmpStart );
535 0 : SwNodeIndex& rRegEndNd = aRegion.End()->nNode;
536 0 : while( IterateNumrulePiece( rRegEndNd,
537 : aTmpStart, aTmpEnd ) )
538 : {
539 0 : SwPaM aTmpPam( aTmpStart, aTmpEnd );
540 : // no start of a new list
541 0 : pDoc->SetNumRule( aTmpPam, *pNumRule, false );
542 :
543 0 : aTmpStart = aTmpEnd; // here starts the next range
544 0 : ++aTmpStart;
545 0 : }
546 : }
547 : else
548 0 : pDoc->DelNumRule( rNumNm );
549 : }
550 : }
551 0 : break;
552 :
553 : case RES_FLTR_BOOKMARK:
554 : {
555 48 : SwFltBookmark* pB = (SwFltBookmark*)rEntry.pAttr;
556 48 : const OUString& rName = ((SwFltBookmark*)rEntry.pAttr)->GetName();
557 :
558 48 : if (IsFlagSet(BOOK_TO_VAR_REF))
559 : {
560 0 : SwFieldType* pFT = pDoc->getIDocumentFieldsAccess().GetFldType(RES_SETEXPFLD, rName, false);
561 0 : if (!pFT)
562 : {
563 0 : SwSetExpFieldType aS(pDoc, rName, nsSwGetSetExpType::GSE_STRING);
564 0 : pFT = pDoc->getIDocumentFieldsAccess().InsertFldType(aS);
565 : }
566 0 : SwSetExpField aFld((SwSetExpFieldType*)pFT, pB->GetValSys());
567 0 : aFld.SetSubType( nsSwExtendedSubType::SUB_INVISIBLE );
568 0 : MakePoint(rEntry, pDoc, aRegion);
569 0 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, SwFmtFld(aFld), 0);
570 0 : MoveAttrs( *(aRegion.GetPoint()) );
571 : }
572 96 : if ( ( !IsFlagSet(HYPO) || IsFlagSet(BOOK_AND_REF) ) &&
573 48 : !rEntry.bConsumedByField )
574 : {
575 44 : MakeBookRegionOrPoint(rEntry, pDoc, aRegion, true);
576 : // #i120879# - create a cross reference heading bookmark if appropriate.
577 : const IDocumentMarkAccess::MarkType eBookmarkType =
578 44 : ( pB->IsTOCBookmark() &&
579 0 : IDocumentMarkAccess::IsLegalPaMForCrossRefHeadingBookmark( aRegion ) )
580 : ? IDocumentMarkAccess::CROSSREF_HEADING_BOOKMARK
581 44 : : IDocumentMarkAccess::BOOKMARK;
582 44 : pDoc->getIDocumentMarkAccess()->makeMark( aRegion, rName, eBookmarkType );
583 : }
584 : }
585 48 : break;
586 : case RES_FLTR_TOX:
587 : {
588 0 : MakePoint(rEntry, pDoc, aRegion);
589 :
590 0 : SwPosition* pPoint = aRegion.GetPoint();
591 :
592 0 : SwFltTOX* pTOXAttr = (SwFltTOX*)rEntry.pAttr;
593 :
594 : // test if on this node there had been a pagebreak BEFORE the
595 : // tox attribute was put on the stack
596 0 : SfxItemSet aBkSet( pDoc->GetAttrPool(), RES_PAGEDESC, RES_BREAK );
597 0 : SwCntntNode* pNd = 0;
598 0 : if( !pTOXAttr->HadBreakItem() || !pTOXAttr->HadPageDescItem() )
599 : {
600 0 : pNd = pPoint->nNode.GetNode().GetCntntNode();
601 0 : if( pNd )
602 : {
603 0 : const SfxItemSet* pSet = pNd->GetpSwAttrSet();
604 : const SfxPoolItem* pItem;
605 0 : if( pSet )
606 : {
607 0 : if( !pTOXAttr->HadBreakItem()
608 0 : && SfxItemState::SET == pSet->GetItemState( RES_BREAK, false, &pItem ) )
609 : {
610 0 : aBkSet.Put( *pItem );
611 0 : pNd->ResetAttr( RES_BREAK );
612 : }
613 0 : if( !pTOXAttr->HadPageDescItem()
614 0 : && SfxItemState::SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem ) )
615 : {
616 0 : aBkSet.Put( *pItem );
617 0 : pNd->ResetAttr( RES_PAGEDESC );
618 : }
619 : }
620 : }
621 : }
622 :
623 0 : delete pTOXAttr->GetBase();
624 :
625 : // set (aboved saved and removed) the break item at the node following the TOX
626 0 : if( aBkSet.Count() )
627 0 : pNd->SetAttr( aBkSet );
628 : }
629 0 : break;
630 : case RES_FLTR_REDLINE:
631 : {
632 0 : if (rEntry.MakeRegion(pDoc, aRegion, true))
633 : {
634 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)( nsRedlineMode_t::REDLINE_ON
635 : | nsRedlineMode_t::REDLINE_SHOW_INSERT
636 0 : | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
637 0 : SwFltRedline& rFltRedline = *((SwFltRedline*)rEntry.pAttr);
638 :
639 0 : if( USHRT_MAX != rFltRedline.nAutorNoPrev )
640 : {
641 : SwRedlineData aData(rFltRedline.eTypePrev,
642 : rFltRedline.nAutorNoPrev,
643 : rFltRedline.aStampPrev,
644 : OUString(),
645 : 0
646 0 : );
647 0 : pDoc->getIDocumentRedlineAccess().AppendRedline(new SwRangeRedline(aData, aRegion), true);
648 : }
649 : SwRedlineData aData(rFltRedline.eType,
650 : rFltRedline.nAutorNo,
651 : rFltRedline.aStamp,
652 : OUString(),
653 : 0
654 0 : );
655 0 : pDoc->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline(aData, aRegion), true );
656 0 : pDoc->getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)( nsRedlineMode_t::REDLINE_NONE
657 : | nsRedlineMode_t::REDLINE_SHOW_INSERT
658 0 : | nsRedlineMode_t::REDLINE_SHOW_DELETE ));
659 : }
660 : }
661 0 : break;
662 : default:
663 : {
664 : // Revised for more complex situations should be considered
665 45148 : if ( !bSdODChecked )
666 : {
667 312 : bHasSdOD = HasSdOD();
668 312 : bSdODChecked = true;
669 : }
670 45148 : sal_Int32 nStart = rEntry.GetStartCP();
671 45148 : sal_Int32 nEnd = rEntry.GetEndCP();
672 45148 : if (nStart != -1 && nEnd != -1 && nEnd >= nStart )
673 : {
674 45148 : rEntry.SetIsParaEnd( IsParaEndInCPs(nStart,nEnd,bHasSdOD) );
675 : }
676 45148 : if (rEntry.MakeRegion(pDoc, aRegion, false))
677 : {
678 39516 : nStart = rEntry.GetStartCP();
679 39516 : nEnd = rEntry.GetEndCP();
680 39516 : if (rEntry.IsParaEnd())
681 : {
682 5844 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, *rEntry.pAttr, 0, true);
683 : }
684 : else
685 : {
686 33672 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, *rEntry.pAttr, 0);
687 : }
688 : }
689 : }
690 45148 : break;
691 45390 : }
692 45390 : }
693 :
694 0 : bool SwFltControlStack::IsParaEndInCPs(sal_Int32 /*nStart*/, sal_Int32 /*nEnd*/,bool /*bSdOD*/) const
695 : {
696 0 : return false;
697 : }
698 :
699 0 : bool SwFltControlStack::CheckSdOD(sal_Int32 /*nStart*/, sal_Int32 /*nEnd*/)
700 : {
701 0 : return false;
702 : }
703 :
704 16 : SfxPoolItem* SwFltControlStack::GetFmtStackAttr(sal_uInt16 nWhich, sal_uInt16 * pPos)
705 : {
706 16 : size_t nSize = maEntries.size();
707 :
708 16 : while (nSize)
709 : {
710 : // is it the looked-for attribute ? (only applies to locked, meaning
711 : // currently set attributes!!)
712 16 : SwFltStackEntry &rEntry = maEntries[--nSize];
713 16 : if (rEntry.bOpen && rEntry.pAttr->Which() == nWhich)
714 : {
715 16 : if (pPos)
716 16 : *pPos = nSize;
717 16 : return (SfxPoolItem*)rEntry.pAttr; // Ok, so stop
718 : }
719 : }
720 0 : return 0;
721 : }
722 :
723 0 : const SfxPoolItem* SwFltControlStack::GetOpenStackAttr(const SwPosition& rPos, sal_uInt16 nWhich)
724 : {
725 0 : SwFltPosition aFltPos(rPos);
726 :
727 0 : size_t nSize = maEntries.size();
728 :
729 0 : while (nSize)
730 : {
731 0 : SwFltStackEntry &rEntry = maEntries[--nSize];
732 0 : if (rEntry.bOpen && rEntry.pAttr->Which() == nWhich && rEntry.m_aMkPos == aFltPos)
733 : {
734 0 : return (SfxPoolItem*)rEntry.pAttr;
735 : }
736 : }
737 0 : return 0;
738 : }
739 :
740 2 : void SwFltControlStack::Delete(const SwPaM &rPam)
741 : {
742 2 : const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
743 :
744 2 : if( !rPam.HasMark() || *pStt >= *pEnd )
745 0 : return;
746 :
747 2 : SwNodeIndex aStartNode(pStt->nNode, -1);
748 2 : const sal_Int32 nStartIdx = pStt->nContent.GetIndex();
749 4 : SwNodeIndex aEndNode(pEnd->nNode, -1);
750 2 : const sal_Int32 nEndIdx = pEnd->nContent.GetIndex();
751 :
752 : // We don't support deleting content that is over one node, or removing a node.
753 : OSL_ENSURE(aEndNode == aStartNode, "nodes must be the same, or this method extended");
754 2 : if (aEndNode != aStartNode)
755 0 : return;
756 :
757 4 : for (size_t nSize = maEntries.size(); nSize > 0;)
758 : {
759 0 : SwFltStackEntry& rEntry = maEntries[--nSize];
760 :
761 : bool bEntryStartAfterSelStart =
762 0 : (rEntry.m_aMkPos.m_nNode == aStartNode &&
763 0 : rEntry.m_aMkPos.m_nCntnt >= nStartIdx);
764 :
765 : bool bEntryStartBeforeSelEnd =
766 0 : (rEntry.m_aMkPos.m_nNode == aEndNode &&
767 0 : rEntry.m_aMkPos.m_nCntnt <= nEndIdx);
768 :
769 0 : bool bEntryEndAfterSelStart = false;
770 0 : bool bEntryEndBeforeSelEnd = false;
771 0 : if (!rEntry.bOpen)
772 : {
773 : bEntryEndAfterSelStart =
774 0 : (rEntry.m_aPtPos.m_nNode == aStartNode &&
775 0 : rEntry.m_aPtPos.m_nCntnt >= nStartIdx);
776 :
777 : bEntryEndBeforeSelEnd =
778 0 : (rEntry.m_aPtPos.m_nNode == aEndNode &&
779 0 : rEntry.m_aPtPos.m_nCntnt <= nEndIdx);
780 : }
781 :
782 0 : bool bTotallyContained = false;
783 0 : if (
784 0 : bEntryStartAfterSelStart && bEntryStartBeforeSelEnd &&
785 0 : bEntryEndAfterSelStart && bEntryEndBeforeSelEnd
786 : )
787 : {
788 0 : bTotallyContained = true;
789 : }
790 :
791 0 : if (bTotallyContained)
792 : {
793 : // after start, before end, delete
794 0 : DeleteAndDestroy(nSize);
795 0 : continue;
796 : }
797 :
798 0 : const sal_Int32 nCntntDiff = nEndIdx - nStartIdx;
799 :
800 : // to be adjusted
801 0 : if (bEntryStartAfterSelStart)
802 : {
803 0 : if (bEntryStartBeforeSelEnd)
804 : {
805 : // move start to new start
806 0 : rEntry.m_aMkPos.SetPos(aStartNode, nStartIdx);
807 : }
808 : else
809 0 : rEntry.m_aMkPos.m_nCntnt -= nCntntDiff;
810 : }
811 :
812 0 : if (bEntryEndAfterSelStart)
813 : {
814 0 : if (bEntryEndBeforeSelEnd)
815 0 : rEntry.m_aPtPos.SetPos(aStartNode, nStartIdx);
816 : else
817 0 : rEntry.m_aPtPos.m_nCntnt -= nCntntDiff;
818 : }
819 :
820 : //That's what Open is, end equal to start, and nPtCntnt is invalid
821 0 : if (rEntry.bOpen)
822 0 : rEntry.m_aPtPos = rEntry.m_aMkPos;
823 2 : }
824 : }
825 :
826 : // methods of SwFltAnchor follow
827 194 : SwFltAnchor::SwFltAnchor(SwFrmFmt* pFmt) :
828 194 : SfxPoolItem(RES_FLTR_ANCHOR), pFrmFmt(pFmt)
829 : {
830 194 : pClient = new SwFltAnchorClient(this);
831 194 : pFrmFmt->Add(pClient);
832 194 : }
833 :
834 194 : SwFltAnchor::SwFltAnchor(const SwFltAnchor& rCpy) :
835 194 : SfxPoolItem(RES_FLTR_ANCHOR), pFrmFmt(rCpy.pFrmFmt)
836 : {
837 194 : pClient = new SwFltAnchorClient(this);
838 194 : pFrmFmt->Add(pClient);
839 194 : }
840 :
841 970 : SwFltAnchor::~SwFltAnchor()
842 : {
843 388 : delete pClient;
844 582 : }
845 :
846 0 : void SwFltAnchor::SetFrmFmt(SwFrmFmt * _pFrmFmt)
847 : {
848 0 : pFrmFmt = _pFrmFmt;
849 0 : }
850 :
851 :
852 :
853 0 : bool SwFltAnchor::operator==(const SfxPoolItem& rItem) const
854 : {
855 0 : return pFrmFmt == ((SwFltAnchor&)rItem).pFrmFmt;
856 : }
857 :
858 194 : SfxPoolItem* SwFltAnchor::Clone(SfxItemPool*) const
859 : {
860 194 : return new SwFltAnchor(*this);
861 : }
862 :
863 388 : SwFltAnchorClient::SwFltAnchorClient(SwFltAnchor * pFltAnchor)
864 388 : : m_pFltAnchor(pFltAnchor)
865 : {
866 388 : }
867 :
868 38 : void SwFltAnchorClient::Modify(const SfxPoolItem *, const SfxPoolItem * pNew)
869 : {
870 38 : if (pNew->Which() == RES_FMT_CHG)
871 : {
872 0 : const SwFmtChg * pFmtChg = dynamic_cast<const SwFmtChg *> (pNew);
873 :
874 0 : if (pFmtChg != NULL)
875 : {
876 0 : SwFrmFmt * pFrmFmt = dynamic_cast<SwFrmFmt *> (pFmtChg->pChangedFmt);
877 :
878 0 : if (pFrmFmt != NULL)
879 0 : m_pFltAnchor->SetFrmFmt(pFrmFmt);
880 : }
881 : }
882 38 : }
883 :
884 : // methods of SwFltRedline follow
885 0 : bool SwFltRedline::operator==(const SfxPoolItem& rItem) const
886 : {
887 0 : return this == &rItem;
888 : }
889 :
890 10 : SfxPoolItem* SwFltRedline::Clone( SfxItemPool* ) const
891 : {
892 10 : return new SwFltRedline(*this);
893 : }
894 :
895 : // methods of SwFltBookmark follow
896 48 : SwFltBookmark::SwFltBookmark( const OUString& rNa, const OUString& rVa,
897 : long nHand, const bool bIsTOCBookmark )
898 : : SfxPoolItem( RES_FLTR_BOOKMARK )
899 : , mnHandle( nHand )
900 : , maName( rNa )
901 : , maVal( rVa )
902 48 : , mbIsTOCBookmark( bIsTOCBookmark )
903 : {
904 : // eSrc: CHARSET_DONTKNOW for no transform at operator <<
905 : // Upcase is always done.
906 : // Transform is never done at XXXStack.NewAttr(...).
907 : // otherwise: Src Charset from argument for aName
908 : // Src Charset from filter for aVal ( Text )
909 :
910 48 : if ( IsTOCBookmark() )
911 : {
912 0 : maName = IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix();
913 0 : maName += rNa;
914 : }
915 48 : }
916 :
917 48 : SwFltBookmark::SwFltBookmark(const SwFltBookmark& rCpy)
918 : : SfxPoolItem( RES_FLTR_BOOKMARK )
919 : , mnHandle( rCpy.mnHandle )
920 : , maName( rCpy.maName )
921 : , maVal( rCpy.maVal )
922 48 : , mbIsTOCBookmark( rCpy.mbIsTOCBookmark )
923 : {
924 48 : }
925 :
926 0 : bool SwFltBookmark::operator==(const SfxPoolItem& rItem) const
927 : {
928 0 : return ( maName == ((SwFltBookmark&)rItem).maName)
929 0 : && (mnHandle == ((SwFltBookmark&)rItem).mnHandle);
930 : }
931 :
932 48 : SfxPoolItem* SwFltBookmark::Clone(SfxItemPool*) const
933 : {
934 48 : return new SwFltBookmark(*this);
935 : }
936 :
937 : // methods of SwFltTOX follow
938 0 : SwFltTOX::SwFltTOX(SwTOXBase* pBase, sal_uInt16 _nCols)
939 : : SfxPoolItem(RES_FLTR_TOX), pTOXBase(pBase), nCols( _nCols ),
940 0 : bHadBreakItem( false ), bHadPageDescItem( false )
941 : {
942 0 : }
943 :
944 0 : SwFltTOX::SwFltTOX(const SwFltTOX& rCpy)
945 : : SfxPoolItem(RES_FLTR_TOX), pTOXBase(rCpy.pTOXBase), nCols( rCpy.nCols ),
946 0 : bHadBreakItem( rCpy.bHadBreakItem ), bHadPageDescItem( rCpy.bHadPageDescItem )
947 : {
948 0 : }
949 :
950 0 : bool SwFltTOX::operator==(const SfxPoolItem& rItem) const
951 : {
952 0 : return pTOXBase == ((SwFltTOX&)rItem).pTOXBase;
953 : }
954 :
955 0 : SfxPoolItem* SwFltTOX::Clone(SfxItemPool*) const
956 : {
957 0 : return new SwFltTOX(*this);
958 : }
959 :
960 : // UpdatePageDescs needs to be called at end of parsing to make Writer actually
961 : // accept Pagedescs contents
962 186 : void UpdatePageDescs(SwDoc &rDoc, sal_uInt16 nInPageDescOffset)
963 : {
964 : // Update document page descriptors (only this way also left pages
965 : // get adjusted)
966 :
967 : // PageDesc "Standard"
968 186 : rDoc.ChgPageDesc(0, rDoc.GetPageDesc(0));
969 :
970 : // PageDescs "Convert..."
971 222 : for (sal_uInt16 i = nInPageDescOffset; i < rDoc.GetPageDescCnt(); ++i)
972 36 : rDoc.ChgPageDesc(i, rDoc.GetPageDesc(i));
973 456 : }
974 :
975 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|