xref: /trunk/main/editeng/source/uno/unoedhlp.cxx (revision 9b8096d0)
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 //IAccessibility2 Implementation 2009-----
32 #include <svl/itemset.hxx>
33 
34 //-----IAccessibility2 Implementation 2009
35 //------------------------------------------------------------------------
36 
37 TYPEINIT1( SvxEditSourceHint, TextHint );
38 
39 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId ) :
40     TextHint( _nId ),
41     mnStart( 0 ),
42     mnEnd( 0 )
43 {
44 }
45 
46 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId, sal_uLong nValue, sal_uLong nStart, sal_uLong nEnd ) :
47     TextHint( _nId, nValue ),
48     mnStart( nStart),
49     mnEnd( nEnd )
50 {
51 }
52 
53 sal_uLong SvxEditSourceHint::GetValue() const
54 {
55     return TextHint::GetValue();
56 }
57 
58 sal_uLong SvxEditSourceHint::GetStartValue() const
59 {
60     return mnStart;
61 }
62 
63 sal_uLong SvxEditSourceHint::GetEndValue() const
64 {
65     return mnEnd;
66 }
67 
68 void SvxEditSourceHint::SetValue( sal_uLong n )
69 {
70     TextHint::SetValue( n );
71 }
72 
73 void SvxEditSourceHint::SetStartValue( sal_uLong n )
74 {
75     mnStart = n;
76 }
77 
78 void SvxEditSourceHint::SetEndValue( sal_uLong n )
79 {
80     mnEnd = n;
81 }
82 //IAccessibility2 Implementation 2009-----
83 TYPEINIT1( SvxEditSourceHintEndPara , SvxEditSourceHint );
84 //-----IAccessibility2 Implementation 2009
85 //------------------------------------------------------------------------
86 
87 ::std::auto_ptr<SfxHint> SvxEditSourceHelper::EENotification2Hint( EENotify* aNotify )
88 {
89     if( aNotify )
90     {
91         switch( aNotify->eNotificationType )
92         {
93             case EE_NOTIFY_TEXTMODIFIED:
94                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_MODIFIED, aNotify->nParagraph ) );
95 
96             case EE_NOTIFY_PARAGRAPHINSERTED:
97                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_PARAINSERTED, aNotify->nParagraph ) );
98 
99             case EE_NOTIFY_PARAGRAPHREMOVED:
100                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_PARAREMOVED, aNotify->nParagraph ) );
101 
102             case EE_NOTIFY_PARAGRAPHSMOVED:
103                 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHint( EDITSOURCE_HINT_PARASMOVED, aNotify->nParagraph, aNotify->nParam1, aNotify->nParam2 ) );
104 
105             case EE_NOTIFY_TEXTHEIGHTCHANGED:
106                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_TEXTHEIGHTCHANGED, aNotify->nParagraph ) );
107 
108             case EE_NOTIFY_TEXTVIEWSCROLLED:
109                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_VIEWSCROLLED ) );
110 
111             case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED:
112                 return ::std::auto_ptr<SfxHint>( new SvxEditSourceHint( EDITSOURCE_HINT_SELECTIONCHANGED ) );
113 
114             case EE_NOTIFY_BLOCKNOTIFICATION_START:
115                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_BLOCKNOTIFICATION_START, 0 ) );
116 
117             case EE_NOTIFY_BLOCKNOTIFICATION_END:
118                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_BLOCKNOTIFICATION_END, 0 ) );
119 
120             case EE_NOTIFY_INPUT_START:
121                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_INPUT_START, 0 ) );
122 
123             case EE_NOTIFY_INPUT_END:
124                 return ::std::auto_ptr<SfxHint>( new TextHint( TEXT_HINT_INPUT_END, 0 ) );
125 	//IAccessibility2 Implementation 2009-----
126 			case EE_NOTIFY_TEXTVIEWSELECTIONCHANGED_ENDD_PARA:
127 				return ::std::auto_ptr<SfxHint>( new SvxEditSourceHintEndPara( EDITSOURCE_HINT_SELECTIONCHANGED ) );
128 	//-----IAccessibility2 Implementation 2009
129             default:
130                 DBG_ERROR( "SvxEditSourceHelper::EENotification2Hint unknown notification" );
131                 break;
132         }
133     }
134 
135     return ::std::auto_ptr<SfxHint>( new SfxHint() );
136 }
137 sal_Bool SvxEditSourceHelper::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, const EditEngine& rEE, sal_uInt16 nPara, sal_uInt16 nIndex, sal_Bool bInCell )
138 {
139 	// IA2 CWS introduced bInCell, but also did many other changes here.
140 	// Need to verify implementation with AT (IA2 and ATK)
141 	// Old implementation at the end of the method for reference...
142 
143 #if 1 // IA2 CWS
144 
145     //added dummy attributes for the default text
146 	EECharAttribArray aCharAttribs, aTempCharAttribs;
147 	rEE.GetCharAttribs( nPara, aTempCharAttribs );
148 	if ( aTempCharAttribs.Count() )
149 	{
150 		sal_uInt32 nIndex2 = 0;
151 		sal_uInt32 nParaLen = rEE.GetTextLen(nPara);
152 		for ( sal_uInt16 nAttr = 0; nAttr < aTempCharAttribs.Count(); nAttr++ )
153 		{
154 			if ( nIndex2 < aTempCharAttribs[nAttr].nStart )
155 			{
156 				EECharAttrib aEEAttr;
157 				aEEAttr.nStart = sal_uInt16(nIndex2);
158 				aEEAttr.nEnd = aTempCharAttribs[nAttr].nStart;
159 				aCharAttribs.Insert( aEEAttr, nAttr );
160 			}
161 			nIndex2 = aTempCharAttribs[nAttr].nEnd;
162 			aCharAttribs.Insert( aTempCharAttribs[nAttr], aCharAttribs.Count() );
163 		}
164 		if ( nIndex2 != nParaLen )
165 		{
166 			EECharAttrib aEEAttr;
167 			aEEAttr.nStart = sal_uInt16(nIndex2);
168 			aEEAttr.nEnd = sal_uInt16(nParaLen);
169 			aCharAttribs.Insert( aEEAttr, aCharAttribs.Count() );
170 		}
171 	}
172     // find closest index in front of nIndex
173     sal_uInt16 nAttr, nCurrIndex;
174     sal_Int32 nClosestStartIndex;
175 	sal_Int32 nClosestStartIndex_s, nClosestStartIndex_e;
176     for( nAttr=0, nClosestStartIndex_s=0, nClosestStartIndex_e=0; nAttr<aCharAttribs.Count(); ++nAttr )
177     {
178         nCurrIndex = aCharAttribs[nAttr].nStart;
179 
180         //if( nCurrIndex > nIndex )
181         //    break; // aCharAttribs array is sorted in increasing order for nStart values
182 
183         if( nCurrIndex > nClosestStartIndex_s &&
184 			nCurrIndex <= nIndex)
185         {
186             nClosestStartIndex_s = nCurrIndex;
187         }
188 		nCurrIndex = aCharAttribs[nAttr].nEnd;
189 		if ( nCurrIndex > nClosestStartIndex_e &&
190 			nCurrIndex < nIndex )
191 		{
192 			nClosestStartIndex_e = nCurrIndex;
193 		}
194     }
195 	nClosestStartIndex = nClosestStartIndex_s > nClosestStartIndex_e ? nClosestStartIndex_s : nClosestStartIndex_e;
196 
197     // find closest index behind of nIndex
198     sal_Int32 nClosestEndIndex;
199 	sal_Int32 nClosestEndIndex_s, nClosestEndIndex_e;
200     for( nAttr=0, nClosestEndIndex_s=nClosestEndIndex_e=rEE.GetTextLen(nPara); nAttr<aCharAttribs.Count(); ++nAttr )
201     {
202         nCurrIndex = aCharAttribs[nAttr].nEnd;
203 
204         if( nCurrIndex > nIndex &&
205             nCurrIndex < nClosestEndIndex_e )
206         {
207             nClosestEndIndex_e = nCurrIndex;
208         }
209 		nCurrIndex = aCharAttribs[nAttr].nStart;
210 		if ( nCurrIndex > nIndex &&
211 			nCurrIndex < nClosestEndIndex_s)
212 		{
213 			nClosestEndIndex_s = nCurrIndex;
214 		}
215     }
216 	nClosestEndIndex = nClosestEndIndex_s < nClosestEndIndex_e ? nClosestEndIndex_s : nClosestEndIndex_e;
217 
218     nStartIndex = static_cast<sal_uInt16>( nClosestStartIndex );
219     nEndIndex = static_cast<sal_uInt16>( nClosestEndIndex );
220 	if ( bInCell )
221 	{
222 		EPosition aStartPos( nPara, nStartIndex ), aEndPos( nPara, nEndIndex );
223 		sal_uInt32 nParaCount = rEE.GetParagraphCount();
224 		sal_uInt32 nCrrntParaLen = rEE.GetTextLen(nPara);
225 		//need to find closest index in front of nIndex in the previous paragraphs
226 		if ( aStartPos.nIndex == 0 )
227 		{
228 			SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, 0, 1, GETATTRIBS_CHARATTRIBS );
229 			for ( sal_Int32 nParaIdx = nPara-1; nParaIdx >= 0; nParaIdx-- )
230 			{
231 				sal_uInt32 nLen = rEE.GetTextLen( sal_uInt16(nParaIdx) );
232 				if ( nLen )
233 				{
234 					sal_uInt16 nStartIdx, nEndIdx;
235 					GetAttributeRun( nStartIdx, nEndIdx, rEE, sal_uInt16(nParaIdx), sal_uInt16(nLen), sal_False );
236 					SfxItemSet aSet = rEE.GetAttribs( sal_uInt16(nParaIdx), sal_uInt16(nLen-1), sal_uInt16(nLen), GETATTRIBS_CHARATTRIBS );
237 					if ( aSet == aCrrntSet )
238 					{
239 						aStartPos.nPara = sal_uInt16(nParaIdx);
240 						aStartPos.nIndex = nStartIdx;
241 						if ( aStartPos.nIndex != 0 )
242 						{
243 							break;
244 						}
245 					}
246 				}
247 			}
248 		}
249 		//need find closest index behind nIndex in the following paragrphs
250 		if ( aEndPos.nIndex == nCrrntParaLen )
251 		{
252 			SfxItemSet aCrrntSet = rEE.GetAttribs( nPara, sal_uInt16(nCrrntParaLen-1), sal_uInt16(nCrrntParaLen), GETATTRIBS_CHARATTRIBS );
253 			for ( sal_uInt32 nParaIdx = nPara+1; nParaIdx < nParaCount; nParaIdx++ )
254 			{
255 				sal_uInt32 nLen = rEE.GetTextLen( sal_uInt16(nParaIdx) );
256 				if ( nLen )
257 				{
258 					sal_uInt16 nStartIdx, nEndIdx;
259 					GetAttributeRun( nStartIdx, nEndIdx, rEE, sal_uInt16(nParaIdx), 0, sal_False );
260 					SfxItemSet aSet = rEE.GetAttribs( sal_uInt16(nParaIdx), 0, 1, GETATTRIBS_CHARATTRIBS );
261 					if ( aSet == aCrrntSet )
262 					{
263 						aEndPos.nPara = sal_uInt16(nParaIdx);
264 						aEndPos.nIndex = nEndIdx;
265 						if ( aEndPos.nIndex != nLen )
266 						{
267 							break;
268 						}
269 					}
270 				}
271 			}
272 		}
273 		nStartIndex = 0;
274 		if ( aStartPos.nPara > 0 )
275 		{
276 			for ( sal_uInt16 i = 0; i < aStartPos.nPara; i++ )
277 			{
278 				nStartIndex += rEE.GetTextLen(i)+1;
279 			}
280 		}
281 		nStartIndex += aStartPos.nIndex;
282 		nEndIndex = 0;
283 		if ( aEndPos.nPara > 0 )
284 		{
285 			for ( sal_uInt16 i = 0; i < aEndPos.nPara; i++ )
286 			{
287 				nEndIndex += rEE.GetTextLen(i)+1;
288 			}
289 		}
290 		nEndIndex += aEndPos.nIndex;
291 	}
292 
293     return sal_True;
294 
295 #else // old implementation
296 
297     EECharAttribArray aCharAttribs;
298 
299     rEE.GetCharAttribs( nPara, aCharAttribs );
300 
301     // find closest index in front of nIndex
302     sal_uInt16 nAttr, nCurrIndex;
303     sal_Int32 nClosestStartIndex;
304     for( nAttr=0, nClosestStartIndex=0; nAttr<aCharAttribs.Count(); ++nAttr )
305     {
306         nCurrIndex = aCharAttribs[nAttr].nStart;
307 
308         if( nCurrIndex > nIndex )
309             break; // aCharAttribs array is sorted in increasing order for nStart values
310 
311         if( nCurrIndex > nClosestStartIndex )
312         {
313             nClosestStartIndex = nCurrIndex;
314         }
315     }
316 
317     // find closest index behind of nIndex
318     sal_Int32 nClosestEndIndex;
319     for( nAttr=0, nClosestEndIndex=rEE.GetTextLen(nPara); nAttr<aCharAttribs.Count(); ++nAttr )
320     {
321         nCurrIndex = aCharAttribs[nAttr].nEnd;
322 
323         if( nCurrIndex > nIndex &&
324             nCurrIndex < nClosestEndIndex )
325         {
326             nClosestEndIndex = nCurrIndex;
327         }
328     }
329 
330     nStartIndex = static_cast<sal_uInt16>( nClosestStartIndex );
331     nEndIndex = static_cast<sal_uInt16>( nClosestEndIndex );
332 
333     return sal_True;
334 
335 #endif
336 }
337 
338 Point SvxEditSourceHelper::EEToUserSpace( const Point& rPoint, const Size& rEESize, bool bIsVertical )
339 {
340     return bIsVertical ? Point( -rPoint.Y() + rEESize.Height(), rPoint.X() ) : rPoint;
341 }
342 
343 Point SvxEditSourceHelper::UserSpaceToEE( const Point& rPoint, const Size& rEESize, bool bIsVertical )
344 {
345     return bIsVertical ? Point( rPoint.Y(), -rPoint.X() + rEESize.Height() ) : rPoint;
346 }
347 
348 Rectangle SvxEditSourceHelper::EEToUserSpace( const Rectangle& rRect, const Size& rEESize, bool bIsVertical )
349 {
350     // #106775# Don't touch rect if not vertical
351     return bIsVertical ? Rectangle( EEToUserSpace(rRect.BottomLeft(), rEESize, bIsVertical),
352                                     EEToUserSpace(rRect.TopRight(), rEESize, bIsVertical) ) : rRect;
353 }
354 
355 Rectangle SvxEditSourceHelper::UserSpaceToEE( const Rectangle& rRect, const Size& rEESize, bool bIsVertical )
356 {
357     // #106775# Don't touch rect if not vertical
358     return bIsVertical ? Rectangle( UserSpaceToEE(rRect.TopRight(), rEESize, bIsVertical),
359                                     UserSpaceToEE(rRect.BottomLeft(), rEESize, bIsVertical) ) : rRect;
360 }
361