1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_editeng.hxx"
26 #include <tools/debug.hxx>
27
28 #include <editeng/unoedhlp.hxx>
29 #include <editeng/editdata.hxx>
30 #include <editeng/editeng.hxx>
31 #include <svl/itemset.hxx>
32
33 //------------------------------------------------------------------------
34
35 TYPEINIT1( SvxEditSourceHint, TextHint );
36
SvxEditSourceHint(sal_uLong _nId)37 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId ) :
38 TextHint( _nId ),
39 mnStart( 0 ),
40 mnEnd( 0 )
41 {
42 }
43
SvxEditSourceHint(sal_uLong _nId,sal_uLong nValue,sal_uLong nStart,sal_uLong nEnd)44 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId, sal_uLong nValue, sal_uLong nStart, sal_uLong nEnd ) :
45 TextHint( _nId, nValue ),
46 mnStart( nStart),
47 mnEnd( nEnd )
48 {
49 }
50
GetValue() const51 sal_uLong SvxEditSourceHint::GetValue() const
52 {
53 return TextHint::GetValue();
54 }
55
GetStartValue() const56 sal_uLong SvxEditSourceHint::GetStartValue() const
57 {
58 return mnStart;
59 }
60
GetEndValue() const61 sal_uLong SvxEditSourceHint::GetEndValue() const
62 {
63 return mnEnd;
64 }
65
SetValue(sal_uLong n)66 void SvxEditSourceHint::SetValue( sal_uLong n )
67 {
68 TextHint::SetValue( n );
69 }
70
SetStartValue(sal_uLong n)71 void SvxEditSourceHint::SetStartValue( sal_uLong n )
72 {
73 mnStart = n;
74 }
75
SetEndValue(sal_uLong n)76 void SvxEditSourceHint::SetEndValue( sal_uLong n )
77 {
78 mnEnd = n;
79 }
80 TYPEINIT1( SvxEditSourceHintEndPara , SvxEditSourceHint );
81 //------------------------------------------------------------------------
82
EENotification2Hint(EENotify * aNotify)83 ::std::auto_ptr<SfxHint> SvxEditSourceHelper::EENotification2Hint( EENotify* aNotify )
84 {
85 if( aNotify )
86 {
87 switch( aNotify->eNotificationType )
88 {
89 case EE_NOTIFY_TEXTMODIFIED:
90 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_MODIFIED, aNotify->nParagraph ) );
91
92 case EE_NOTIFY_PARAGRAPHINSERTED:
93 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_PARAINSERTED, aNotify->nParagraph ) );
94
95 case EE_NOTIFY_PARAGRAPHREMOVED:
96 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_PARAREMOVED, aNotify->nParagraph ) );
97
98 case EE_NOTIFY_PARAGRAPHSMOVED:
99 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHint( EDITSOURCE_HINT_PARASMOVED, aNotify->nParagraph, aNotify->nParam1, aNotify->nParam2 ) );
100
101 case EE_NOTIFY_TEXTHEIGHTCHANGED:
102 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_TEXTHEIGHTCHANGED, aNotify->nParagraph ) );
103
104 case EE_NOTIFY_TEXTVIEWSCROLLED:
105 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_VIEWSCROLLED ) );
106
107 case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED:
108 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHint( EDITSOURCE_HINT_SELECTIONCHANGED ) );
109
110 case EE_NOTIFY_BLOCKNOTIFICATION_START:
111 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_BLOCKNOTIFICATION_START, 0 ) );
112
113 case EE_NOTIFY_BLOCKNOTIFICATION_END:
114 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_BLOCKNOTIFICATION_END, 0 ) );
115
116 case EE_NOTIFY_INPUT_START:
117 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_INPUT_START, 0 ) );
118
119 case EE_NOTIFY_INPUT_END:
120 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_INPUT_END, 0 ) );
121 case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED_ENDD_PARA:
122 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHintEndPara( EDITSOURCE_HINT_SELECTIONCHANGED ) );
123 default:
124 DBG_ERROR( "SvxEditSourceHelper::EENotification2Hint unknown notification" );
125 break;
126 }
127 }
128
129 return ::std::auto_ptr<SfxHint>( new SfxHint() );
130 }
GetAttributeRun(sal_uInt16 & nStartIndex,sal_uInt16 & nEndIndex,const EditEngine & rEE,sal_uInt16 nPara,sal_uInt16 nIndex,sal_Bool bInCell)131 sal_Bool SvxEditSourceHelper::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, const EditEngine& rEE, sal_uInt16 nPara, sal_uInt16 nIndex, sal_Bool bInCell )
132 {
133 // IA2 CWS introduced bInCell, but also did many other changes here.
134 // Need to verify implementation with AT (IA2 and ATK)
135 // Old implementation at the end of the method for reference...
136
137 #if 1
138 //added dummy attributes for the default text
139 EECharAttribArray aCharAttribs, aTempCharAttribs;
140 rEE.GetCharAttribs( nPara, aTempCharAttribs );
141 if ( aTempCharAttribs.Count() )
142 {
143 sal_uInt32 nIndex2 = 0;
144 sal_uInt32 nParaLen = rEE.GetTextLen(nPara);
145 for ( sal_uInt16 nAttr = 0; nAttr < aTempCharAttribs.Count(); nAttr++ )
146 {
147 if ( nIndex2 < aTempCharAttribs[nAttr].nStart )
148 {
149 EECharAttrib aEEAttr;
150 aEEAttr.nStart = sal_uInt16(nIndex2);
151 aEEAttr.nEnd = aTempCharAttribs[nAttr].nStart;
152 aCharAttribs.Insert( aEEAttr, nAttr );
153 }
154 nIndex2 = aTempCharAttribs[nAttr].nEnd;
155 aCharAttribs.Insert( aTempCharAttribs[nAttr], aCharAttribs.Count() );
156 }
157 if ( nIndex2 != nParaLen )
158 {
159 EECharAttrib aEEAttr;
160 aEEAttr.nStart = sal_uInt16(nIndex2);
161 aEEAttr.nEnd = sal_uInt16(nParaLen);
162 aCharAttribs.Insert( aEEAttr, aCharAttribs.Count() );
163 }
164 }
165 // find closest index in front of nIndex
166 sal_uInt16 nAttr, nCurrIndex;
167 sal_Int32 nClosestStartIndex;
168 sal_Int32 nClosestStartIndex_s, nClosestStartIndex_e;
169 for( nAttr=0, nClosestStartIndex_s=0, nClosestStartIndex_e=0; nAttr<aCharAttribs.Count(); ++nAttr )
170 {
171 nCurrIndex = aCharAttribs[nAttr].nStart;
172
173 //if( nCurrIndex > nIndex )
174 // break; // aCharAttribs array is sorted in increasing order for nStart values
175
176 if( nCurrIndex > nClosestStartIndex_s &&
177 nCurrIndex <= nIndex)
178 {
179 nClosestStartIndex_s = nCurrIndex;
180 }
181 nCurrIndex = aCharAttribs[nAttr].nEnd;
182 if ( nCurrIndex > nClosestStartIndex_e &&
183 nCurrIndex < nIndex )
184 {
185 nClosestStartIndex_e = nCurrIndex;
186 }
187 }
188 nClosestStartIndex = nClosestStartIndex_s > nClosestStartIndex_e ? nClosestStartIndex_s : nClosestStartIndex_e;
189
190 // find closest index behind of nIndex
191 sal_Int32 nClosestEndIndex;
192 sal_Int32 nClosestEndIndex_s, nClosestEndIndex_e;
193 for( nAttr=0, nClosestEndIndex_s=nClosestEndIndex_e=rEE.GetTextLen(nPara); nAttr<aCharAttribs.Count(); ++nAttr )
194 {
195 nCurrIndex = aCharAttribs[nAttr].nEnd;
196
197 if( nCurrIndex > nIndex &&
198 nCurrIndex < nClosestEndIndex_e )
199 {
200 nClosestEndIndex_e = nCurrIndex;
201 }
202 nCurrIndex = aCharAttribs[nAttr].nStart;
203 if ( nCurrIndex > nIndex &&
204 nCurrIndex < nClosestEndIndex_s)
205 {
206 nClosestEndIndex_s = nCurrIndex;
207 }
208 }
209 nClosestEndIndex = nClosestEndIndex_s < nClosestEndIndex_e ? nClosestEndIndex_s : nClosestEndIndex_e;
210
211 nStartIndex = static_cast<sal_uInt16>( nClosestStartIndex );
212 nEndIndex = static_cast<sal_uInt16>( nClosestEndIndex );
213 if ( bInCell )
214 {
215 EPosition aStartPos( nPara, nStartIndex ), aEndPos( nPara, nEndIndex );
216 sal_uInt32 nParaCount = rEE.GetParagraphCount();
217 sal_uInt32 nCrrntParaLen = rEE.GetTextLen(nPara);
218 //need to find closest index in front of nIndex in the previous paragraphs
219 if ( aStartPos.nIndex == 0 )
220 {
221 SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, 0, 1, GETATTRIBS_CHARATTRIBS );
222 for ( sal_Int32 nParaIdx = nPara-1; nParaIdx >= 0; nParaIdx-- )
223 {
224 sal_uInt32 nLen = rEE.GetTextLen( sal_uInt16(nParaIdx) );
225 if ( nLen )
226 {
227 sal_uInt16 nStartIdx, nEndIdx;
228 GetAttributeRun( nStartIdx, nEndIdx, rEE, sal_uInt16(nParaIdx), sal_uInt16(nLen), sal_False );
229 SfxItemSet aSet = rEE.GetAttribs( sal_uInt16(nParaIdx), sal_uInt16(nLen-1), sal_uInt16(nLen), GETATTRIBS_CHARATTRIBS );
230 if ( aSet == aCrrntSet )
231 {
232 aStartPos.nPara = sal_uInt16(nParaIdx);
233 aStartPos.nIndex = nStartIdx;
234 if ( aStartPos.nIndex != 0 )
235 {
236 break;
237 }
238 }
239 }
240 }
241 }
242 //need find closest index behind nIndex in the following paragrphs
243 if ( aEndPos.nIndex == nCrrntParaLen )
244 {
245 SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, sal_uInt16(nCrrntParaLen-1), sal_uInt16(nCrrntParaLen), GETATTRIBS_CHARATTRIBS );
246 for ( sal_uInt32 nParaIdx = nPara+1; nParaIdx < nParaCount; nParaIdx++ )
247 {
248 sal_uInt32 nLen = rEE.GetTextLen( sal_uInt16(nParaIdx) );
249 if ( nLen )
250 {
251 sal_uInt16 nStartIdx, nEndIdx;
252 GetAttributeRun( nStartIdx, nEndIdx, rEE, sal_uInt16(nParaIdx), 0, sal_False );
253 SfxItemSet aSet = rEE.GetAttribs( sal_uInt16(nParaIdx), 0, 1, GETATTRIBS_CHARATTRIBS );
254 if ( aSet == aCrrntSet )
255 {
256 aEndPos.nPara = sal_uInt16(nParaIdx);
257 aEndPos.nIndex = nEndIdx;
258 if ( aEndPos.nIndex != nLen )
259 {
260 break;
261 }
262 }
263 }
264 }
265 }
266 nStartIndex = 0;
267 if ( aStartPos.nPara > 0 )
268 {
269 for ( sal_uInt16 i = 0; i < aStartPos.nPara; i++ )
270 {
271 nStartIndex += rEE.GetTextLen(i)+1;
272 }
273 }
274 nStartIndex += aStartPos.nIndex;
275 nEndIndex = 0;
276 if ( aEndPos.nPara > 0 )
277 {
278 for ( sal_uInt16 i = 0; i < aEndPos.nPara; i++ )
279 {
280 nEndIndex += rEE.GetTextLen(i)+1;
281 }
282 }
283 nEndIndex += aEndPos.nIndex;
284 }
285
286 return sal_True;
287
288 #else // old implementation
289
290 EECharAttribArray aCharAttribs;
291
292 rEE.GetCharAttribs( nPara, aCharAttribs );
293
294 // find closest index in front of nIndex
295 sal_uInt16 nAttr, nCurrIndex;
296 sal_Int32 nClosestStartIndex;
297 for( nAttr=0, nClosestStartIndex=0; nAttr<aCharAttribs.Count(); ++nAttr )
298 {
299 nCurrIndex = aCharAttribs[nAttr].nStart;
300
301 if( nCurrIndex > nIndex )
302 break; // aCharAttribs array is sorted in increasing order for nStart values
303
304 if( nCurrIndex > nClosestStartIndex )
305 {
306 nClosestStartIndex = nCurrIndex;
307 }
308 }
309
310 // find closest index behind of nIndex
311 sal_Int32 nClosestEndIndex;
312 for( nAttr=0, nClosestEndIndex=rEE.GetTextLen(nPara); nAttr<aCharAttribs.Count(); ++nAttr )
313 {
314 nCurrIndex = aCharAttribs[nAttr].nEnd;
315
316 if( nCurrIndex > nIndex &&
317 nCurrIndex < nClosestEndIndex )
318 {
319 nClosestEndIndex = nCurrIndex;
320 }
321 }
322
323 nStartIndex = static_cast<sal_uInt16>( nClosestStartIndex );
324 nEndIndex = static_cast<sal_uInt16>( nClosestEndIndex );
325
326 return sal_True;
327
328 #endif
329 }
330
EEToUserSpace(const Point & rPoint,const Size & rEESize,bool bIsVertical)331 Point SvxEditSourceHelper::EEToUserSpace( const Point& rPoint, const Size& rEESize, bool bIsVertical )
332 {
333 return bIsVertical ? Point( -rPoint.Y() + rEESize.Height(), rPoint.X() ) : rPoint;
334 }
335
UserSpaceToEE(const Point & rPoint,const Size & rEESize,bool bIsVertical)336 Point SvxEditSourceHelper::UserSpaceToEE( const Point& rPoint, const Size& rEESize, bool bIsVertical )
337 {
338 return bIsVertical ? Point( rPoint.Y(), -rPoint.X() + rEESize.Height() ) : rPoint;
339 }
340
EEToUserSpace(const Rectangle & rRect,const Size & rEESize,bool bIsVertical)341 Rectangle SvxEditSourceHelper::EEToUserSpace( const Rectangle& rRect, const Size& rEESize, bool bIsVertical )
342 {
343 // #106775# Don't touch rect if not vertical
344 return bIsVertical ? Rectangle( EEToUserSpace(rRect.BottomLeft(), rEESize, bIsVertical),
345 EEToUserSpace(rRect.TopRight(), rEESize, bIsVertical) ) : rRect;
346 }
347
UserSpaceToEE(const Rectangle & rRect,const Size & rEESize,bool bIsVertical)348 Rectangle SvxEditSourceHelper::UserSpaceToEE( const Rectangle& rRect, const Size& rEESize, bool bIsVertical )
349 {
350 // #106775# Don't touch rect if not vertical
351 return bIsVertical ? Rectangle( UserSpaceToEE(rRect.TopRight(), rEESize, bIsVertical),
352 UserSpaceToEE(rRect.BottomLeft(), rEESize, bIsVertical) ) : rRect;
353 }
354