xref: /trunk/main/editeng/source/uno/unoedhlp.cxx (revision 4d7c9de0)
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 
37 SvxEditSourceHint::SvxEditSourceHint( sal_uLong _nId ) :
38     TextHint( _nId ),
39     mnStart( 0 ),
40     mnEnd( 0 )
41 {
42 }
43 
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 
51 sal_uLong SvxEditSourceHint::GetValue() const
52 {
53     return TextHint::GetValue();
54 }
55 
56 sal_uLong SvxEditSourceHint::GetStartValue() const
57 {
58     return mnStart;
59 }
60 
61 sal_uLong SvxEditSourceHint::GetEndValue() const
62 {
63     return mnEnd;
64 }
65 
66 void SvxEditSourceHint::SetValue( sal_uLong n )
67 {
68     TextHint::SetValue( n );
69 }
70 
71 void SvxEditSourceHint::SetStartValue( sal_uLong n )
72 {
73     mnStart = n;
74 }
75 
76 void SvxEditSourceHint::SetEndValue( sal_uLong n )
77 {
78     mnEnd = n;
79 }
80 TYPEINIT1( SvxEditSourceHintEndPara , SvxEditSourceHint );
81 //------------------------------------------------------------------------
82 
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 }
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 
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 
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 
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 
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