/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
static sal_Int16
text_type_from_boundary(AtkTextBoundary boundary_type)
{ switch(boundary_type)
{ case ATK_TEXT_BOUNDARY_CHAR: return accessibility::AccessibleTextType::CHARACTER; case ATK_TEXT_BOUNDARY_WORD_START: case ATK_TEXT_BOUNDARY_WORD_END: return accessibility::AccessibleTextType::WORD; case ATK_TEXT_BOUNDARY_SENTENCE_START: case ATK_TEXT_BOUNDARY_SENTENCE_END: return accessibility::AccessibleTextType::SENTENCE; case ATK_TEXT_BOUNDARY_LINE_START: case ATK_TEXT_BOUNDARY_LINE_END: return accessibility::AccessibleTextType::LINE; default: return -1;
}
}
if( !rTextSegment.SegmentText.isEmpty() )
{ switch(boundary_type)
{ case ATK_TEXT_BOUNDARY_CHAR: if ((rTextSegment.SegmentEnd - rTextSegment.SegmentStart) == 1
&& rtl::isSurrogate(rTextSegment.SegmentText[0])) return nullptr;
[[fallthrough]]; case ATK_TEXT_BOUNDARY_LINE_START: case ATK_TEXT_BOUNDARY_LINE_END: case ATK_TEXT_BOUNDARY_SENTENCE_START:
start = rTextSegment.SegmentStart;
end = rTextSegment.SegmentEnd;
aString = rTextSegment.SegmentText; break;
// the OOo break iterator behaves as SENTENCE_START case ATK_TEXT_BOUNDARY_SENTENCE_END:
start = rTextSegment.SegmentStart;
end = rTextSegment.SegmentEnd;
if( start > 0 )
--start; if( end > 0 && end < pText->getCharacterCount() - 1 )
--end;
aString = pText->getTextRange(start, end); break;
case ATK_TEXT_BOUNDARY_WORD_START:
start = rTextSegment.SegmentStart;
// Determine the start index of the next segment
aTextSegment = pText->getTextBehindIndex(rTextSegment.SegmentEnd,
text_type_from_boundary(boundary_type)); if( !aTextSegment.SegmentText.isEmpty() )
end = aTextSegment.SegmentStart; else
end = pText->getCharacterCount();
aString = pText->getTextRange(start, end); break;
case ATK_TEXT_BOUNDARY_WORD_END:
end = rTextSegment.SegmentEnd;
// Determine the end index of the previous segment
aTextSegment = pText->getTextBeforeIndex(rTextSegment.SegmentStart,
text_type_from_boundary(boundary_type)); if( !aTextSegment.SegmentText.isEmpty() )
start = aTextSegment.SegmentEnd; else
start = 0;
static gchar *
text_wrapper_get_text_at_offset (AtkText *text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{ try {
css::uno::Reference<css::accessibility::XAccessibleText> pText
= getText( text ); if( pText.is() )
{ /* If the user presses the 'End' key, the caret will be placed behind the last character, * which is the same index as the first character of the next line. In atk the magic offset * '-2' is used to cover this special case.
*/ if (
-2 == offset &&
(ATK_TEXT_BOUNDARY_LINE_START == boundary_type ||
ATK_TEXT_BOUNDARY_LINE_END == boundary_type)
)
{
css::uno::Reference<
css::accessibility::XAccessibleMultiLineText> pMultiLineText
= getMultiLineText( text ); if( pMultiLineText.is() )
{
accessibility::TextSegment aTextSegment = pMultiLineText->getTextAtLineWithCaret(); return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
}
}
css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
pTextAttributes = getTextAttributes( text ); if(pTextAttributes.is()) // Text attributes are available for paragraphs only
{
aAttributeList = pTextAttributes->getRunAttributes( offset, uno::Sequence< OUString > () );
} else// For other text objects use character attributes
{
aAttributeList = pText->getCharacterAttributes( offset, uno::Sequence< OUString > () );
}
pSet = attribute_set_new_from_property_values( aAttributeList, true, text ); // #i100938# // - always provide start_offset and end_offset
{
accessibility::TextSegment aTextSegment =
pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
*start_offset = aTextSegment.SegmentStart; // #i100938# // Do _not_ increment the end_offset provide by <accessibility::TextSegment> instance
*end_offset = aTextSegment.SegmentEnd;
bOffsetsAreValid = true;
}
}
// Special handling for misspelled text // #i92232# // - add special handling for tracked changes and refactor the // corresponding code for handling misspelled text.
css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
pTextMarkup = getTextMarkup( text ); if( pTextMarkup.is() )
{ // Get attribute run here if it hasn't been done before if (!bOffsetsAreValid && pText.is())
{
accessibility::TextSegment aAttributeTextSegment =
pText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN);
*start_offset = aAttributeTextSegment.SegmentStart;
*end_offset = aAttributeTextSegment.SegmentEnd;
} // handle misspelled text
pSet = handle_text_markup_as_run_attribute(
pTextMarkup,
css::text::TextMarkupType::SPELLCHECK,
offset, pSet, start_offset, end_offset ); // handle tracked changes
pSet = handle_text_markup_as_run_attribute(
pTextMarkup,
css::text::TextMarkupType::TRACK_CHANGE_INSERTION,
offset, pSet, start_offset, end_offset );
pSet = handle_text_markup_as_run_attribute(
pTextMarkup,
css::text::TextMarkupType::TRACK_CHANGE_DELETION,
offset, pSet, start_offset, end_offset );
pSet = handle_text_markup_as_run_attribute(
pTextMarkup,
css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE,
offset, pSet, start_offset, end_offset );
}
} catch(const uno::Exception&){
return OUStringToGChar( pText->getSelectedText() );
}
} catch(const uno::Exception&) {
g_warning( "Exception in getSelectionEnd(), getSelectionStart() or getSelectedText()" );
}
return nullptr;
}
static gboolean
text_wrapper_add_selection (AtkText *text,
gint start_offset,
gint end_offset)
{ // FIXME: can we try to be more compatible by expanding an // existing adjacent selection ?
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.