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  * AccEditableText.cpp : Implementation of CUAccCOMApp and DLL registration.
24  */
25 #include "stdafx.h"
26 #include "UAccCOM2.h"
27 #include "AccEditableText.h"
28 #include <com/sun/star/accessibility/XAccessible.hpp>
29 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
30 #include <com/sun/star/accessibility/XAccessibleText.hpp>
31 #include <com/sun/star/awt/FontSlant.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/style/LineSpacing.hpp>
34 #include <com/sun/star/style/TabStop.hpp>
35 #include <vector>
36 
37 using namespace com::sun::star::accessibility;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::awt;
40 using namespace com::sun::star::beans;
41 using namespace std;
42 
43 /**
44  * Copys a range of text to the clipboard.
45  *
46  * @param    startOffset    the start offset of copying.
47  * @param    endOffset      the end offset of copying.
48  * @param    success        the boolean result to be returned.
49  */
copyText(long startOffset,long endOffset)50 STDMETHODIMP CAccEditableText::copyText(long startOffset, long endOffset)
51 {
52 
53 	CHECK_ENABLE_INF
54 
55     ENTER_PROTECTED_BLOCK
56 
57     // #CHECK XInterface#
58     if(!pRXEdtTxt.is())
59     {
60         return E_FAIL;
61     }
62 
63     if ( GetXInterface()->copyText( startOffset, endOffset ) )
64         return S_OK;
65 
66     return E_FAIL;
67 
68     LEAVE_PROTECTED_BLOCK
69 }
70 
71 /**
72  * Deletes a range of text.
73  *
74  * @param    startOffset    the start offset of deleting.
75  * @param    endOffset      the end offset of deleting.
76  * @param    success        the boolean result to be returned.
77  */
deleteText(long startOffset,long endOffset)78 STDMETHODIMP CAccEditableText::deleteText(long startOffset, long endOffset)
79 {
80 
81 	CHECK_ENABLE_INF
82 
83     ENTER_PROTECTED_BLOCK
84 
85     if( !pRXEdtTxt.is() )
86         return E_FAIL;
87 
88     if( GetXInterface()->deleteText( startOffset, endOffset ) )
89         return S_OK;
90 
91     return E_FAIL;
92 
93     LEAVE_PROTECTED_BLOCK
94 }
95 
96 /**
97  * Inserts text at a specified offset.
98  *
99  * @param    offset    the offset of inserting.
100  * @param    text      the text to be inserted.
101  * @param    success   the boolean result to be returned.
102  */
insertText(long offset,BSTR * text)103 STDMETHODIMP CAccEditableText::insertText(long offset, BSTR * text)
104 {
105 
106 	CHECK_ENABLE_INF
107 
108     ENTER_PROTECTED_BLOCK
109 
110     if (text == NULL)
111         return E_INVALIDARG;
112 
113     if( !pRXEdtTxt.is() )
114         return E_FAIL;
115 
116     ::rtl::OUString ouStr(*text);
117 
118     if( GetXInterface()->insertText( ouStr, offset ) )
119         return S_OK;
120 
121     return E_FAIL;
122 
123     LEAVE_PROTECTED_BLOCK
124 }
125 
126 /**
127  * Cuts a range of text to the clipboard.
128  *
129  * @param    startOffset    the start offset of cuting.
130  * @param    endOffset      the end offset of cuting.
131  * @param    success        the boolean result to be returned.
132  */
cutText(long startOffset,long endOffset)133 STDMETHODIMP CAccEditableText::cutText(long startOffset, long endOffset)
134 {
135 
136 	CHECK_ENABLE_INF
137 
138     ENTER_PROTECTED_BLOCK
139 
140     if( !pRXEdtTxt.is() )
141         return E_FAIL;
142 
143     if( GetXInterface()->cutText( startOffset, endOffset ) )
144         return S_OK;
145 
146     return E_FAIL;
147 
148     LEAVE_PROTECTED_BLOCK
149 }
150 
151 /**
152  * Pastes text from clipboard at specified offset.
153  *
154  * @param    offset    the offset of pasting.
155  * @param    success   the boolean result to be returned.
156  */
pasteText(long offset)157 STDMETHODIMP CAccEditableText::pasteText(long offset)
158 {
159 
160 	CHECK_ENABLE_INF
161 
162     ENTER_PROTECTED_BLOCK
163 
164     if( !pRXEdtTxt.is() )
165         return E_FAIL;
166 
167     if( GetXInterface()->pasteText( offset ) )
168         return S_OK;
169 
170     return E_FAIL;
171 
172     LEAVE_PROTECTED_BLOCK
173 }
174 
175 /**
176  * Replaces range of text with new text.
177  *
178  * @param    startOffset    the start offset of replacing.
179  * @param    endOffset      the end offset of replacing.
180  * @param    text           the replacing text.
181  * @param    success        the boolean result to be returned.
182  */
replaceText(long startOffset,long endOffset,BSTR * text)183 STDMETHODIMP CAccEditableText::replaceText(long startOffset, long endOffset, BSTR * text)
184 {
185 
186 	CHECK_ENABLE_INF
187 
188     ENTER_PROTECTED_BLOCK
189 
190     // #CHECK#
191     if (text == NULL)
192         return E_INVALIDARG;
193     if( !pRXEdtTxt.is() )
194         return E_FAIL;
195 
196     ::rtl::OUString ouStr(*text);
197 
198     if( GetXInterface()->replaceText( startOffset,endOffset, ouStr) )
199         return S_OK;
200     return E_FAIL;
201 
202     LEAVE_PROTECTED_BLOCK
203 }
204 
205 /**
206  * Sets attributes of range of text.
207  *
208  * @param    startOffset    the start offset.
209  * @param    endOffset      the end offset.
210  * @param    attributes     the attribute text.
211  * @param    success        the boolean result to be returned.
212  */
setAttributes(long startOffset,long endOffset,BSTR * attributes)213 STDMETHODIMP CAccEditableText::setAttributes(long startOffset, long endOffset, BSTR * attributes)
214 {
215 
216 	CHECK_ENABLE_INF
217 
218     ENTER_PROTECTED_BLOCK
219 
220     // #CHECK#
221     if (attributes == NULL)
222         return E_INVALIDARG;
223     if( !pRXEdtTxt.is() )
224         return E_FAIL;
225 
226     ::rtl::OUString ouStr(*attributes);
227 
228     sal_Int32 nIndex = 0;
229     sal_Unicode cTok = ';';
230     vector< ::rtl::OUString > vecAttr;
231     do
232     {
233         ::rtl::OUString ouToken = ouStr.getToken(0, cTok, nIndex);
234         vecAttr.push_back(ouToken);
235     }
236     while(nIndex >= 0);
237 
238     Sequence< PropertyValue > beanSeq(vecAttr.size());
239     for(unsigned int i = 0; i < vecAttr.size(); i ++)
240     {
241         ::rtl::OUString attr = vecAttr[i];
242         sal_Int32 nPos = attr.indexOf(':');
243         if(nPos > -1)
244         {
245             ::rtl::OUString attrName = attr.copy(0, nPos);
246             ::rtl::OUString attrValue = attr.copy(nPos + 1, attr.getLength() - nPos - 1);
247             beanSeq[i].Name = attrName;
248             get_AnyFromOLECHAR(attrName, attrValue, beanSeq[i].Value);
249         }
250     }
251 
252     if( GetXInterface()->setAttributes( startOffset,endOffset, beanSeq) )
253         return S_OK;
254 
255     return E_FAIL;
256 
257     LEAVE_PROTECTED_BLOCK
258 }
259 
260 /**
261  * Convert attributes string to Any type.
262  * Reference to infra\accessibility\bridge\org\openoffice\java\accessibility\AccessibleTextImpl.java
263  *
264  * @param	ouName		the string of attribute name.
265  * @param	ouValue		the string of attribute value.
266  * @param	rAny		the Any object to be returned.
267  */
get_AnyFromOLECHAR(const::rtl::OUString & ouName,const::rtl::OUString & ouValue,Any & rAny)268 void CAccEditableText::get_AnyFromOLECHAR(const ::rtl::OUString &ouName, const ::rtl::OUString &ouValue, Any &rAny)
269 {
270     if(ouName.compareTo(L"CharBackColor") == 0 ||
271             ouName.compareTo(L"CharColor") == 0 ||
272             ouName.compareTo(L"ParaAdjust") == 0 ||
273             ouName.compareTo(L"ParaFirstLineIndent") == 0 ||
274             ouName.compareTo(L"ParaLeftMargin") == 0 ||
275             ouName.compareTo(L"ParaRightMargin") == 0 ||
276             ouName.compareTo(L"ParaTopMargin") == 0 ||
277             ouName.compareTo(L"ParaBottomMargin") == 0 ||
278             ouName.compareTo(L"CharFontPitch") == 0)
279     {
280         // Convert to int.
281         // NOTE: CharFontPitch is not implemented in java file.
282         sal_Int32 nValue = ouValue.toInt32();
283         rAny.setValue(&nValue, getCppuType((sal_Int32 *)0));
284     }
285     else if(ouName.compareTo(L"CharShadowed") == 0 ||
286             ouName.compareTo(L"CharContoured") == 0)
287     {
288         // Convert to boolean.
289         boolean nValue = (boolean)ouValue.toBoolean();
290         rAny.setValue(&nValue, getCppuType((sal_Bool *)sal_False));
291     }
292     else if(ouName.compareTo(L"CharEscapement") == 0 ||
293             ouName.compareTo(L"CharStrikeout") == 0 ||
294             ouName.compareTo(L"CharUnderline") == 0 ||
295             ouName.compareTo(L"CharFontPitch") == 0)
296     {
297         // Convert to short.
298         short nValue = (short)ouValue.toInt32();
299         rAny.setValue(&nValue, getCppuType((short *)0));
300     }
301     else if(ouName.compareTo(L"CharHeight") == 0 ||
302             ouName.compareTo(L"CharWeight") == 0)
303     {
304         // Convert to float.
305         float fValue = ouValue.toFloat();
306         rAny.setValue(&fValue, getCppuType((float *)0));
307     }
308     else if(ouName.compareTo(L"CharFontName") == 0)
309     {
310         // Convert to string.
311         rAny.setValue(&ouValue, getCppuType((::rtl::OUString *)0));
312     }
313     else if(ouName.compareTo(L"CharPosture") == 0)
314     {
315         // Convert to FontSlant.
316         ::com::sun::star::awt::FontSlant fontSlant = (::com::sun::star::awt::FontSlant)ouValue.toInt32();
317         rAny.setValue(&fontSlant, getCppuType((::com::sun::star::awt::FontSlant*)0));
318     }
319     else if(ouName.compareTo(L"ParaTabStops") == 0)
320     {
321         //
322         // Convert to the Sequence with TabStop element.
323         vector< ::com::sun::star::style::TabStop > vecTabStop;
324         ::com::sun::star::style::TabStop tabStop;
325         ::rtl::OUString ouSubValue;
326         sal_Int32 nIndex = 0;
327         sal_Int32 pos = 0, posComma = 0;
328 
329         do
330         {
331             // Position.
332             pos = ouValue.indexOf(L"Position=", pos);
333             if(pos != -1)
334             {
335                 posComma = ouValue.indexOf(',', pos + 9); // 9 = length of "Position=".
336                 if(posComma != -1)
337                 {
338                     ouSubValue = ouValue.copy(pos + 9, posComma - pos - 9);
339                     tabStop.Position = ouSubValue.toInt32();
340                     pos = posComma + 1;
341 
342                     // TabAlign.
343                     pos = ouValue.indexOf(L"TabAlign=", pos);
344                     if(pos != -1)
345                     {
346                         posComma = ouValue.indexOf(',', pos + 9); // 9 = length of "TabAlign=".
347                         if(posComma != -1)
348                         {
349                             ouSubValue = ouValue.copy(pos + 9, posComma - pos - 9);
350                             tabStop.Alignment = (::com::sun::star::style::TabAlign)ouSubValue.toInt32();
351                             pos = posComma + 1;
352 
353                             // DecimalChar.
354                             pos = ouValue.indexOf(L"DecimalChar=", pos);
355                             if(pos != -1)
356                             {
357                                 posComma = ouValue.indexOf(',', pos + 11); // 11 = length of "TabAlign=".
358                                 if(posComma != -1)
359                                 {
360                                     ouSubValue = ouValue.copy(pos + 11, posComma - pos - 11);
361                                     tabStop.DecimalChar = (sal_Unicode)ouSubValue.toChar();
362                                     pos = posComma + 1;
363 
364                                     // FillChar.
365                                     pos = ouValue.indexOf(L"FillChar=", pos);
366                                     if(pos != -1)
367                                     {
368                                         posComma = ouValue.indexOf(',', pos + 9); // 9 = length of "TabAlign=".
369                                         if(posComma != -1)
370                                         {
371                                             ouSubValue = ouValue.copy(pos + 9, posComma - pos - 9);
372                                             tabStop.DecimalChar = (sal_Unicode)ouSubValue.toChar();
373                                             pos = posComma + 1;
374 
375                                             // Complete TabStop element.
376                                             vecTabStop.push_back(tabStop);
377                                         }
378                                         else
379                                             break;	// No match comma.
380                                     }
381                                     else
382                                         break;	// No match FillChar.
383                                 }
384                                 else
385                                     break;	// No match comma.
386                             }
387                             else
388                                 break;	// No match DecimalChar.
389                         }
390                         else
391                             break;	// No match comma.
392                     }
393                     else
394                         break;	// No match TabAlign.
395                 }
396                 else
397                     break;	// No match comma.
398             }
399             else
400                 break;	// No match Position.
401         }
402         while(pos < ouValue.getLength());
403 
404         //
405         // Dump into Sequence.
406         int iSeqLen = (vecTabStop.size() == 0) ? 1 : vecTabStop.size();
407         Sequence< ::com::sun::star::style::TabStop > seqTabStop(iSeqLen);
408 
409         if(vecTabStop.size() != 0)
410         {
411             // Dump every element.
412             for(int i = 0; i < iSeqLen; i ++)
413             {
414                 seqTabStop[i] = vecTabStop[i];
415             }
416         }
417         else
418         {
419             // Create default value.
420             seqTabStop[0].Position = 0;
421             seqTabStop[0].Alignment = ::com::sun::star::style::TabAlign_DEFAULT;
422             seqTabStop[0].DecimalChar = '.';
423             seqTabStop[0].FillChar = ' ';
424         }
425 
426         // Assign to Any object.
427         rAny.setValue(&seqTabStop, getCppuType((Sequence< ::com::sun::star::style::TabStop >*)0));
428     }
429     else if(ouName.compareTo(L"ParaLineSpacing") == 0)
430     {
431         // Parse value string.
432         ::com::sun::star::style::LineSpacing lineSpacing;
433         ::rtl::OUString ouSubValue;
434         sal_Int32 pos = 0, posComma = 0;
435 
436         pos = ouValue.indexOf(L"Mode=", pos);
437         if(pos != -1)
438         {
439             posComma = ouValue.indexOf(',', pos + 5); // 5 = length of "Mode=".
440             if(posComma != -1)
441             {
442                 ouSubValue = ouValue.copy(pos + 5, posComma - pos - 5);
443                 lineSpacing.Mode = (sal_Int16)ouSubValue.toInt32();
444                 pos = posComma + 1;
445 
446                 pos = ouValue.indexOf(L"Height=", pos);
447                 if(pos != -1)
448                 {
449                     ouSubValue = ouValue.copy(pos + 7, ouValue.getLength() - pos - 7);
450                     lineSpacing.Height = (sal_Int16)ouSubValue.toInt32();
451                 }
452                 else
453                 {
454                     lineSpacing.Height = (sal_Int16)100;	// Default height.
455                 }
456             }
457             else
458             {
459                 lineSpacing.Height = (sal_Int16)100;	// Default height.
460             }
461         }
462         else
463         {
464             // Default Mode and Height.
465             lineSpacing.Mode = (sal_Int16)0;
466             lineSpacing.Height = (sal_Int16)100;	// Default height.
467         }
468 
469         // Convert to Any object.
470         rAny.setValue(&lineSpacing, getCppuType((::com::sun::star::style::LineSpacing* )0));
471     }
472     else
473     {
474         // Do nothing.
475         sal_Int32 nDefault = 0;
476         rAny.setValue(&nDefault, getCppuType((sal_Int32 *)0));
477     }
478 }
479 
480 /**
481  * Overide of IUNOXWrapper.
482  *
483  * @param    pXInterface    the pointer of UNO interface.
484  */
put_XInterface(long pXInterface)485 STDMETHODIMP CAccEditableText::put_XInterface(long pXInterface)
486 {
487 
488 
489     ENTER_PROTECTED_BLOCK
490 
491     CUNOXWrapper::put_XInterface(pXInterface);
492     //special query.
493     if(pUNOInterface == NULL)
494         return E_FAIL;
495     Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
496     if( !pRContext.is() )
497     {
498         return E_FAIL;
499     }
500     Reference<XAccessibleEditableText> pRXI(pRContext,UNO_QUERY);
501     if( !pRXI.is() )
502         pRXEdtTxt = NULL;
503     else
504         pRXEdtTxt = pRXI.get();
505     return S_OK;
506 
507     LEAVE_PROTECTED_BLOCK
508 }
509