Avoid potential negative array index access to cached text.
[LibreOffice.git] / winaccessibility / source / UAccCOM / AccEditableText.cxx
blob212546e12ee08dd284d87fff3f7712be2d82a48c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 /**
21 * AccEditableText.cpp : Implementation of CUAccCOMApp and DLL registration.
23 #include "stdafx.h"
24 #include <UAccCOM.h>
25 #include "AccEditableText.h"
27 #include <vcl/svapp.hxx>
28 #include <o3tl/char16_t2wchar_t.hxx>
30 #include <com/sun/star/accessibility/XAccessible.hpp>
31 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
32 #include <com/sun/star/accessibility/XAccessibleText.hpp>
33 #include <com/sun/star/awt/FontSlant.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/style/LineSpacing.hpp>
36 #include <com/sun/star/style/TabStop.hpp>
37 #include <vector>
39 using namespace com::sun::star::accessibility;
40 using namespace com::sun::star::uno;
41 using namespace com::sun::star::awt;
42 using namespace com::sun::star::beans;
44 /**
45 * Copy a range of text to the clipboard.
47 * @param startOffset the start offset of copying.
48 * @param endOffset the end offset of copying.
49 * @param success the boolean result to be returned.
51 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::copyText(long startOffset, long endOffset)
53 SolarMutexGuard g;
55 try {
57 if(!pRXEdtTxt.is())
59 return E_FAIL;
62 if ( GetXInterface()->copyText( startOffset, endOffset ) )
63 return S_OK;
65 return E_FAIL;
67 } catch(...) { return E_FAIL; }
70 /**
71 * Deletes a range of text.
73 * @param startOffset the start offset of deleting.
74 * @param endOffset the end offset of deleting.
75 * @param success the boolean result to be returned.
77 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::deleteText(long startOffset, long endOffset)
79 SolarMutexGuard g;
81 try {
83 if( !pRXEdtTxt.is() )
84 return E_FAIL;
86 if( GetXInterface()->deleteText( startOffset, endOffset ) )
87 return S_OK;
89 return E_FAIL;
91 } catch(...) { return E_FAIL; }
94 /**
95 * Inserts text at a specified offset.
97 * @param offset the offset of inserting.
98 * @param text the text to be inserted.
99 * @param success the boolean result to be returned.
101 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::insertText(long offset, BSTR * text)
103 SolarMutexGuard g;
105 try {
107 if (text == nullptr)
108 return E_INVALIDARG;
110 if( !pRXEdtTxt.is() )
111 return E_FAIL;
113 OUString ouStr(o3tl::toU(*text));
115 if( GetXInterface()->insertText( ouStr, offset ) )
116 return S_OK;
118 return E_FAIL;
120 } catch(...) { return E_FAIL; }
124 * Cuts a range of text to the clipboard.
126 * @param startOffset the start offset of cutting.
127 * @param endOffset the end offset of cutting.
128 * @param success the boolean result to be returned.
130 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::cutText(long startOffset, long endOffset)
132 SolarMutexGuard g;
134 try {
136 if( !pRXEdtTxt.is() )
137 return E_FAIL;
139 if( GetXInterface()->cutText( startOffset, endOffset ) )
140 return S_OK;
142 return E_FAIL;
144 } catch(...) { return E_FAIL; }
148 * Pastes text from clipboard at specified offset.
150 * @param offset the offset of pasting.
151 * @param success the boolean result to be returned.
153 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::pasteText(long offset)
155 SolarMutexGuard g;
157 try {
159 if( !pRXEdtTxt.is() )
160 return E_FAIL;
162 if( GetXInterface()->pasteText( offset ) )
163 return S_OK;
165 return E_FAIL;
167 } catch(...) { return E_FAIL; }
171 * Replaces range of text with new text.
173 * @param startOffset the start offset of replacing.
174 * @param endOffset the end offset of replacing.
175 * @param text the replacing text.
176 * @param success the boolean result to be returned.
178 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::replaceText(long startOffset, long endOffset, BSTR * text)
180 SolarMutexGuard g;
182 try {
184 if (text == nullptr)
185 return E_INVALIDARG;
186 if( !pRXEdtTxt.is() )
187 return E_FAIL;
189 OUString ouStr(o3tl::toU(*text));
191 if( GetXInterface()->replaceText( startOffset,endOffset, ouStr) )
192 return S_OK;
193 return E_FAIL;
195 } catch(...) { return E_FAIL; }
199 * Sets attributes of range of text.
201 * @param startOffset the start offset.
202 * @param endOffset the end offset.
203 * @param attributes the attribute text.
204 * @param success the boolean result to be returned.
206 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::setAttributes(long startOffset, long endOffset, BSTR * attributes)
208 SolarMutexGuard g;
210 try {
212 if (attributes == nullptr)
213 return E_INVALIDARG;
214 if( !pRXEdtTxt.is() )
215 return E_FAIL;
217 OUString ouStr(o3tl::toU(*attributes));
219 std::vector< OUString > vecAttr;
220 for (sal_Int32 nIndex {0}; nIndex >= 0; )
221 vecAttr.push_back(ouStr.getToken(0, ';', nIndex));
223 Sequence< PropertyValue > beanSeq(vecAttr.size());
224 auto beanSeqRange = asNonConstRange(beanSeq);
225 for(std::vector<OUString>::size_type i = 0; i < vecAttr.size(); i ++)
227 OUString attr = vecAttr[i];
228 sal_Int32 nPos = attr.indexOf(':');
229 if(nPos > -1)
231 OUString attrName = attr.copy(0, nPos);
232 OUString attrValue = attr.copy(nPos + 1);
233 beanSeqRange[i].Name = attrName;
234 get_AnyFromOLECHAR(attrName, attrValue, beanSeqRange[i].Value);
238 if( GetXInterface()->setAttributes( startOffset,endOffset, beanSeq) )
239 return S_OK;
241 return E_FAIL;
243 } catch(...) { return E_FAIL; }
247 * Convert attributes string to Any type.
249 * @param ouName the string of attribute name.
250 * @param ouValue the string of attribute value.
251 * @param rAny the Any object to be returned.
253 void CAccEditableText::get_AnyFromOLECHAR(std::u16string_view ouName, const OUString &ouValue, Any &rAny)
255 if(ouName == u"CharBackColor" ||
256 ouName == u"CharColor" ||
257 ouName == u"ParaAdjust" ||
258 ouName == u"ParaFirstLineIndent" ||
259 ouName == u"ParaLeftMargin" ||
260 ouName == u"ParaRightMargin" ||
261 ouName == u"ParaTopMargin" ||
262 ouName == u"ParaBottomMargin" ||
263 ouName == u"CharFontPitch" )
265 // Convert to int.
266 // NOTE: CharFontPitch is not implemented in java file.
267 sal_Int32 nValue = ouValue.toInt32();
268 rAny.setValue(&nValue, cppu::UnoType<sal_Int32>::get());
270 else if(ouName == u"CharShadowed" ||
271 ouName == u"CharContoured" )
273 // Convert to boolean.
274 rAny <<= ouValue.toBoolean();
276 else if(ouName == u"CharEscapement" ||
277 ouName == u"CharStrikeout" ||
278 ouName == u"CharUnderline" ||
279 ouName == u"CharFontPitch" )
281 // Convert to short.
282 short nValue = static_cast<short>(ouValue.toInt32());
283 rAny.setValue(&nValue, cppu::UnoType<short>::get());
285 else if(ouName == u"CharHeight" ||
286 ouName == u"CharWeight" )
288 // Convert to float.
289 float fValue = ouValue.toFloat();
290 rAny.setValue(&fValue, cppu::UnoType<float>::get());
292 else if(ouName == u"CharFontName" )
294 // Convert to string.
295 rAny.setValue(&ouValue, cppu::UnoType<OUString>::get());
297 else if(ouName == u"CharPosture" )
299 // Convert to FontSlant.
300 css::awt::FontSlant fontSlant = static_cast<css::awt::FontSlant>(ouValue.toInt32());
301 rAny.setValue(&fontSlant, cppu::UnoType<css::awt::FontSlant>::get());
303 else if(ouName == u"ParaTabStops" )
306 // Convert to the Sequence with TabStop element.
307 std::vector< css::style::TabStop > vecTabStop;
308 css::style::TabStop tabStop;
309 OUString ouSubValue;
310 sal_Int32 pos = 0, posComma = 0;
314 // Position.
315 pos = ouValue.indexOf("Position=", pos);
316 if(pos != -1)
318 posComma = ouValue.indexOf(',', pos + 9); // 9 = length of "Position=".
319 if(posComma != -1)
321 ouSubValue = ouValue.copy(pos + 9, posComma - pos - 9);
322 tabStop.Position = ouSubValue.toInt32();
323 pos = posComma + 1;
325 // TabAlign.
326 pos = ouValue.indexOf("TabAlign=", pos);
327 if(pos != -1)
329 posComma = ouValue.indexOf(',', pos + 9); // 9 = length of "TabAlign=".
330 if(posComma != -1)
332 ouSubValue = ouValue.copy(pos + 9, posComma - pos - 9);
333 tabStop.Alignment = static_cast<css::style::TabAlign>(ouSubValue.toInt32());
334 pos = posComma + 1;
336 // DecimalChar.
337 pos = ouValue.indexOf("DecimalChar=", pos);
338 if(pos != -1)
340 posComma = ouValue.indexOf(',', pos + 11); // 11 = length of "TabAlign=".
341 if(posComma != -1)
343 ouSubValue = ouValue.copy(pos + 11, posComma - pos - 11);
344 tabStop.DecimalChar = ouSubValue.toChar();
345 pos = posComma + 1;
347 // FillChar.
348 pos = ouValue.indexOf("FillChar=", pos);
349 if(pos != -1)
351 posComma = ouValue.indexOf(',', pos + 9); // 9 = length of "TabAlign=".
352 if(posComma != -1)
354 ouSubValue = ouValue.copy(pos + 9, posComma - pos - 9);
355 tabStop.DecimalChar = ouSubValue.toChar();
356 pos = posComma + 1;
358 // Complete TabStop element.
359 vecTabStop.push_back(tabStop);
361 else
362 break; // No match comma.
364 else
365 break; // No match FillChar.
367 else
368 break; // No match comma.
370 else
371 break; // No match DecimalChar.
373 else
374 break; // No match comma.
376 else
377 break; // No match TabAlign.
379 else
380 break; // No match comma.
382 else
383 break; // No match Position.
385 while(pos < ouValue.getLength());
388 // Dump into Sequence.
389 int iSeqLen = vecTabStop.empty() ? 1 : vecTabStop.size();
390 Sequence< css::style::TabStop > seqTabStop(iSeqLen);
391 auto pseqTabStop = seqTabStop.getArray();
393 if (!vecTabStop.empty())
395 // Dump every element.
396 for(int i = 0; i < iSeqLen; i ++)
398 pseqTabStop[i] = vecTabStop[i];
401 else
403 // Create default value.
404 pseqTabStop[0].Position = 0;
405 pseqTabStop[0].Alignment = css::style::TabAlign_DEFAULT;
406 pseqTabStop[0].DecimalChar = '.';
407 pseqTabStop[0].FillChar = ' ';
410 // Assign to Any object.
411 rAny.setValue(&seqTabStop, cppu::UnoType<Sequence< css::style::TabStop >>::get());
413 else if(ouName == u"ParaLineSpacing" )
415 // Parse value string.
416 css::style::LineSpacing lineSpacing;
417 OUString ouSubValue;
418 sal_Int32 pos = 0, posComma = 0;
420 pos = ouValue.indexOf("Mode=", pos);
421 if(pos != -1)
423 posComma = ouValue.indexOf(',', pos + 5); // 5 = length of "Mode=".
424 if(posComma != -1)
426 ouSubValue = ouValue.copy(pos + 5, posComma - pos - 5);
427 lineSpacing.Mode = static_cast<sal_Int16>(ouSubValue.toInt32());
428 pos = posComma + 1;
430 pos = ouValue.indexOf("Height=", pos);
431 if(pos != -1)
433 ouSubValue = ouValue.copy(pos + 7);
434 lineSpacing.Height = static_cast<sal_Int16>(ouSubValue.toInt32());
436 else
438 lineSpacing.Height = sal_Int16(100); // Default height.
441 else
443 lineSpacing.Height = sal_Int16(100); // Default height.
446 else
448 // Default Mode and Height.
449 lineSpacing.Mode = sal_Int16(0);
450 lineSpacing.Height = sal_Int16(100); // Default height.
453 // Convert to Any object.
454 rAny.setValue(&lineSpacing, cppu::UnoType<css::style::LineSpacing>::get());
456 else
458 // Do nothing.
459 sal_Int32 nDefault = 0;
460 rAny.setValue(&nDefault, cppu::UnoType<sal_Int32>::get());
465 * Override of IUNOXWrapper.
467 * @param pXInterface the pointer of UNO interface.
469 COM_DECLSPEC_NOTHROW STDMETHODIMP CAccEditableText::put_XInterface(hyper pXInterface)
471 // internal IUNOXWrapper - no mutex meeded
473 try {
475 CUNOXWrapper::put_XInterface(pXInterface);
476 //special query.
477 if(pUNOInterface == nullptr)
478 return E_FAIL;
479 Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
480 if( !pRContext.is() )
482 return E_FAIL;
484 Reference<XAccessibleEditableText> pRXI(pRContext,UNO_QUERY);
485 if( !pRXI.is() )
486 pRXEdtTxt = nullptr;
487 else
488 pRXEdtTxt = pRXI.get();
489 return S_OK;
491 } catch(...) { return E_FAIL; }
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */