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