1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_SW_SOURCE_CORE_INC_WRONG_HXX
21 #define INCLUDED_SW_SOURCE_CORE_INC_WRONG_HXX
23 #include <com/sun/star/container/NoSuchElementException.hpp>
24 #include <com/sun/star/container/XStringKeyMap.hpp>
26 #include <com/sun/star/awt/FontUnderline.hpp>
27 #include <com/sun/star/uno/Any.hxx>
33 #include <tools/color.hxx>
34 #include <swtypes.hxx>
35 #include <viewopt.hxx>
36 #include "TextFrameIndex.hxx"
39 // For MSVC (without /vmg) SwTextNode must consistently be defined for
40 // WrongListIterator::m_pGetWrongList of pointer-to-SwTextNode-member type to consistently have the
41 // same size in all translation units that include this file:
47 enum WrongAreaLineType
61 WRONGLIST_CHANGETRACKING
69 css::uno::Reference
< css::container::XStringKeyMap
> mxPropertyBag
;
72 SwWrongList
* mpSubList
;
75 WrongAreaLineType mLineType
;
77 SwWrongArea( OUString aType
,
78 WrongListType listType
,
79 css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
,
83 SwWrongArea( OUString aType
,
84 css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
,
87 SwWrongList
* pSubList
);
90 static Color
getGrammarColor ( css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
)
94 if (xPropertyBag
.is())
96 css::uno::Any aLineColor
= xPropertyBag
->getValue("LineColor");
99 if (aLineColor
>>= lineColor
)
105 catch(const css::container::NoSuchElementException
&)
108 catch(const css::uno::RuntimeException
&)
112 return SwViewOption::GetCurrentViewOptions().GetGrammarColor();
115 static WrongAreaLineType
getGrammarLineType( css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
)
119 if (xPropertyBag
.is())
121 css::uno::Any aLineType
= xPropertyBag
->getValue("LineType");
122 ::sal_Int16 lineType
= 0;
124 if (!(aLineType
>>= lineType
))
126 return WRONGAREA_WAVE
;
128 if (css::awt::FontUnderline::BOLDWAVE
== lineType
)
130 return WRONGAREA_BOLDWAVE
;
132 if (css::awt::FontUnderline::BOLD
== lineType
)
134 return WRONGAREA_BOLD
;
136 if (css::awt::FontUnderline::DASH
== lineType
)
138 return WRONGAREA_DASHED
;
140 if (css::awt::FontUnderline::SMALLWAVE
== lineType
)
142 return WRONGAREA_WAVE
; //Code draws wave height based on space that fits.
146 catch(const css::container::NoSuchElementException
&)
149 catch(const css::uno::RuntimeException
&)
153 return WRONGAREA_WAVE
;
156 static Color
getSmartColor ( css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
)
160 if (xPropertyBag
.is())
162 css::uno::Any aLineColor
= xPropertyBag
->getValue("LineColor");
165 if (aLineColor
>>= lineColor
)
171 catch(const css::container::NoSuchElementException
&)
174 catch(const css::uno::RuntimeException
&)
178 return SwViewOption::GetCurrentViewOptions().GetSmarttagColor();
181 static WrongAreaLineType
getSmartLineType( css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
)
185 if (xPropertyBag
.is())
187 css::uno::Any aLineType
= xPropertyBag
->getValue("LineType");
188 ::sal_Int16 lineType
= 0;
190 if (!(aLineType
>>= lineType
))
192 return WRONGAREA_DASHED
;
194 if (css::awt::FontUnderline::WAVE
== lineType
)
196 return WRONGAREA_WAVE
;
198 if (css::awt::FontUnderline::BOLDWAVE
== lineType
)
200 return WRONGAREA_BOLDWAVE
;
202 if (css::awt::FontUnderline::BOLD
== lineType
)
204 return WRONGAREA_BOLD
;
206 if (css::awt::FontUnderline::SMALLWAVE
== lineType
)
208 return WRONGAREA_WAVE
; //Code draws wave height based on space that fits.
212 catch(const css::container::NoSuchElementException
&)
215 catch(const css::uno::RuntimeException
&)
219 return WRONGAREA_DASHED
;
222 static Color
getWrongAreaColor(WrongListType listType
,
223 css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
)
225 if (WRONGLIST_SPELL
== listType
)
227 return SwViewOption::GetCurrentViewOptions().GetSpellColor();
229 else if (WRONGLIST_GRAMMAR
== listType
)
231 return getGrammarColor(xPropertyBag
);
233 else if (WRONGLIST_SMARTTAG
== listType
)
235 return getSmartColor(xPropertyBag
);
238 return SwViewOption::GetCurrentViewOptions().GetSpellColor();
241 static WrongAreaLineType
getWrongAreaLineType(WrongListType listType
,
242 css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
)
244 if (WRONGLIST_SPELL
== listType
)
246 return WRONGAREA_WAVE
;
248 else if (WRONGLIST_GRAMMAR
== listType
)
250 return getGrammarLineType(xPropertyBag
);
252 else if (WRONGLIST_SMARTTAG
== listType
)
254 return getSmartLineType(xPropertyBag
);
257 return WRONGAREA_WAVE
;
262 class SAL_DLLPUBLIC_RTTI SwWrongList
264 std::vector
<SwWrongArea
> maList
;
265 WrongListType meType
;
267 sal_Int32 mnBeginInvalid
; // Start of the invalid range
268 sal_Int32 mnEndInvalid
; // End of the invalid range
270 static void ShiftLeft( sal_Int32
&rPos
, sal_Int32 nStart
, sal_Int32 nEnd
)
271 { if( rPos
> nStart
) rPos
= rPos
> nEnd
? rPos
- nEnd
+ nStart
: nStart
; }
272 void Invalidate_( sal_Int32 nBegin
, sal_Int32 nEnd
);
274 void Insert(sal_uInt16 nWhere
, std::vector
<SwWrongArea
>::iterator startPos
, std::vector
<SwWrongArea
>::iterator
const & endPos
);
275 void Remove( sal_uInt16 nIdx
, sal_uInt16 nLen
);
277 SwWrongList
& operator= (const SwWrongList
&) = delete;
278 SwWrongList( const SwWrongList
& rCpy
) = delete;
281 SwWrongList( WrongListType eType
);
283 virtual ~SwWrongList();
284 virtual SwWrongList
* Clone();
285 virtual void CopyFrom( const SwWrongList
& rCopy
);
287 WrongListType
GetWrongListType() const { return meType
; }
288 sal_Int32
GetBeginInv() const { return mnBeginInvalid
; }
289 sal_Int32
GetEndInv() const { return mnEndInvalid
; }
290 void SetInvalid( sal_Int32 nBegin
, sal_Int32 nEnd
);
291 void Validate(){ mnBeginInvalid
= mnEndInvalid
= COMPLETE_STRING
; }
292 void Invalidate( sal_Int32 nBegin
, sal_Int32 nEnd
);
293 bool InvalidateWrong();
294 enum class FreshState
{ FRESH
, CURSOR
, NOTHING
};
295 FreshState
Fresh( sal_Int32
&rStart
, sal_Int32
&rEnd
, sal_Int32 nPos
,
296 sal_Int32 nLen
, sal_uInt16 nIndex
, sal_Int32 nCursorPos
);
297 sal_uInt16
GetWrongPos( sal_Int32 nValue
) const;
299 bool Check( sal_Int32
&rChk
, sal_Int32
&rLn
) const;
300 bool InWrongWord( sal_Int32
&rChk
, sal_Int32
&rLn
) const;
301 sal_Int32
NextWrong( sal_Int32 nChk
) const;
303 void Move( sal_Int32 nPos
, sal_Int32 nDiff
);
306 // Divide the list into two part, the wrong words until nSplitPos will be
307 // removed and transferred to a new SwWrongList.
308 std::unique_ptr
<SwWrongList
> SplitList( sal_Int32 nSplitPos
);
309 // Join the next SwWrongList, nInsertPos is my own text length, where
310 // the other wrong list has to be inserted.
311 void JoinList( SwWrongList
* pNext
, sal_Int32 nInsertPos
);
313 sal_Int32
Len( sal_uInt16 nIdx
) const
315 return nIdx
< maList
.size() ? maList
[nIdx
].mnLen
: 0;
318 sal_Int32
Pos( sal_uInt16 nIdx
) const
320 return nIdx
< maList
.size() ? maList
[nIdx
].mnPos
: 0;
323 sal_uInt16
Count() const { return o3tl::narrowing
<sal_uInt16
>(maList
.size()); }
325 void Insert( const OUString
& rType
,
326 css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
,
327 sal_Int32 nNewPos
, sal_Int32 nNewLen
, sal_uInt16 nWhere
)
329 std::vector
<SwWrongArea
>::iterator i
= maList
.begin();
330 if ( nWhere
>= maList
.size() )
331 i
= maList
.end(); // robust
335 maList
.insert(i
, SwWrongArea( rType
, meType
, xPropertyBag
, nNewPos
, nNewLen
) );
338 void Insert( const OUString
& rType
,
339 css::uno::Reference
< css::container::XStringKeyMap
> const & xPropertyBag
,
340 sal_Int32 nNewPos
, sal_Int32 nNewLen
);
342 SwWrongList
* SubList( sal_uInt16 nIdx
) const
344 return nIdx
< maList
.size() ? maList
[nIdx
].mpSubList
: nullptr;
347 void InsertSubList( sal_Int32 nNewPos
, sal_Int32 nNewLen
, sal_uInt16 nWhere
, SwWrongList
* pSubList
);
349 const SwWrongArea
* GetElement( sal_uInt16 nIdx
) const
351 return nIdx
< maList
.size() ? &maList
[nIdx
] : nullptr;
353 void RemoveEntry( sal_Int32 nBegin
, sal_Int32 nEnd
);
354 bool LookForEntry( sal_Int32 nBegin
, sal_Int32 nEnd
);
364 class WrongListIteratorBase
367 SwWrongList
const* (SwTextNode::*const m_pGetWrongList
)() const;
368 sw::MergedPara
const*const m_pMergedPara
;
369 size_t m_CurrentExtent
;
370 TextFrameIndex m_CurrentIndex
;
371 SwWrongList
const*const m_pWrongList
;
374 /// for the text frame
375 WrongListIteratorBase(SwTextFrame
const& rFrame
,
376 SwWrongList
const* (SwTextNode::*pGetWrongList
)() const);
378 WrongListIteratorBase(SwWrongList
const& rWrongList
);
381 class WrongListIterator
382 : public WrongListIteratorBase
385 /// for the text frame
386 WrongListIterator(SwTextFrame
const& rFrame
,
387 SwWrongList
const* (SwTextNode::*pGetWrongList
)() const);
389 WrongListIterator(SwWrongList
const& rWrongList
);
391 bool Check(TextFrameIndex
&rStart
, TextFrameIndex
&rLen
);
392 const SwWrongArea
* GetWrongElement(TextFrameIndex nStart
);
394 bool LooksUseful() { return m_pMergedPara
|| m_pWrongList
; }
397 class WrongListIteratorCounter
398 : public WrongListIteratorBase
401 WrongListIteratorCounter(SwTextFrame
const& rFrame
,
402 SwWrongList
const* (SwTextNode::*pGetWrongList
)() const);
403 WrongListIteratorCounter(SwWrongList
const& rWrongList
);
405 sal_uInt16
GetElementCount();
406 std::optional
<std::pair
<TextFrameIndex
, TextFrameIndex
>> GetElementAt(sal_uInt16 nIndex
);
413 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */