Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/vcl/unx/gtk3/a11y/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 29 kB image not shown  

Quelle  atktext.cxx   Sprache: C

 
/* -*- 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 .
 */


#include "atkwrapper.hxx"
#include "atktextattributes.hxx"
#include <algorithm>

#include <osl/diagnose.h>
#include <rtl/character.hxx>

#include <com/sun/star/accessibility/AccessibleScrollType.hpp>
#include <com/sun/star/accessibility/AccessibleTextType.hpp>
#include <com/sun/star/accessibility/TextSegment.hpp>
#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
#include <com/sun/star/accessibility/XAccessibleText.hpp>
#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp>
#include <com/sun/star/lang/NoSupportException.hpp>
#include <com/sun/star/text/TextMarkupType.hpp>

using namespace ::com::sun::star;

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 ATK_CHECK_VERSION(2,32,0)
static accessibility::AccessibleScrollType
scroll_type_from_scroll_type(AtkScrollType type)
{
    switch(type)
    {
        case ATK_SCROLL_TOP_LEFT:
            return accessibility::AccessibleScrollType_SCROLL_TOP_LEFT;
        case ATK_SCROLL_BOTTOM_RIGHT:
            return accessibility::AccessibleScrollType_SCROLL_BOTTOM_RIGHT;
        case ATK_SCROLL_TOP_EDGE:
            return accessibility::AccessibleScrollType_SCROLL_TOP_EDGE;
        case ATK_SCROLL_BOTTOM_EDGE:
            return accessibility::AccessibleScrollType_SCROLL_BOTTOM_EDGE;
        case ATK_SCROLL_LEFT_EDGE:
            return accessibility::AccessibleScrollType_SCROLL_LEFT_EDGE;
        case ATK_SCROLL_RIGHT_EDGE:
            return accessibility::AccessibleScrollType_SCROLL_RIGHT_EDGE;
        case ATK_SCROLL_ANYWHERE:
            return accessibility::AccessibleScrollType_SCROLL_ANYWHERE;
        default:
            throw lang::NoSupportException();
    }
}
#endif

/*****************************************************************************/

static gchar *
adjust_boundaries( css::uno::Reference<css::accessibility::XAccessibleText> const &&nbsp;pText,
                   accessibility::TextSegment const & rTextSegment,
                   AtkTextBoundary  boundary_type,
                   gint * start_offset, gint * end_offset )
{
    accessibility::TextSegment aTextSegment;
    OUString aString;
    gint start = 0, end = 0;

    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;

            aString = pText->getTextRange(start, end);
            break;

        default:
            return nullptr;
        }
    }

    *start_offset = start;
    *end_offset   = end;

    return OUStringToGChar(aString);
}

/*****************************************************************************/

/// @throws uno::RuntimeException
static css::uno::Reference<css::accessibility::XAccessibleText>
    getText( AtkText *pText )
{
    AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
    if( pWrap )
    {
        if( !pWrap->mpText.is() )
        {
            pWrap->mpText.set(pWrap->mpContext, css::uno::UNO_QUERY);
        }

        return pWrap->mpText;
    }

    return css::uno::Reference<css::accessibility::XAccessibleText>();
}

/*****************************************************************************/

/// @throws uno::RuntimeException
static css::uno::Reference<css::accessibility::XAccessibleTextMarkup>
    getTextMarkup( AtkText *pText )
{
    AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
    if( pWrap )
    {
        if( !pWrap->mpTextMarkup.is() )
        {
            pWrap->mpTextMarkup.set(pWrap->mpContext, css::uno::UNO_QUERY);
        }

        return pWrap->mpTextMarkup;
    }

    return css::uno::Reference<css::accessibility::XAccessibleTextMarkup>();
}

/*****************************************************************************/

/// @throws uno::RuntimeException
static css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
    getTextAttributes( AtkText *pText )
{
    AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
    if( pWrap )
    {
        if( !pWrap->mpTextAttributes.is() )
        {
            pWrap->mpTextAttributes.set(pWrap->mpContext, css::uno::UNO_QUERY);
        }

        return pWrap->mpTextAttributes;
    }

    return css::uno::Reference<css::accessibility::XAccessibleTextAttributes>();
}

/*****************************************************************************/

/// @throws uno::RuntimeException
static css::uno::Reference<css::accessibility::XAccessibleMultiLineText>
    getMultiLineText( AtkText *pText )
{
    AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
    if( pWrap )
    {
        if( !pWrap->mpMultiLineText.is() )
        {
            pWrap->mpMultiLineText.set(pWrap->mpContext, css::uno::UNO_QUERY);
        }

        return pWrap->mpMultiLineText;
    }

    return css::uno::Reference<css::accessibility::XAccessibleMultiLineText>();
}

/*****************************************************************************/

extern "C" {

static gchar *
text_wrapper_get_text (AtkText *text,
                       gint     start_offset,
                       gint     end_offset)
{
    gchar * ret = nullptr;

    g_return_val_if_fail( (end_offset == -1) || (end_offset >= start_offset), nullptr );

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
        {
            OUString aText;
            sal_Int32 n = pText->getCharacterCount();

            if( start_offset < n )
            {
                if( -1 == end_offset )
                    aText = pText->getTextRange(start_offset, n - start_offset);
                else
                    aText = pText->getTextRange(start_offset, end_offset);
            }

            ret = g_strdup( OUStringToOString(aText, RTL_TEXTENCODING_UTF8 ).getStr() );
        }
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in getText()" );
    }

    return ret;
}

static gchar *
text_wrapper_get_text_after_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() )
        {
            accessibility::TextSegment aTextSegment = pText->getTextBehindIndex(offset, text_type_from_boundary(boundary_type));
            return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
        }
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in get_text_after_offset()" );
    }

    return nullptr;
}

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);
                }
            }

            accessibility::TextSegment aTextSegment = pText->getTextAtIndex(offset, text_type_from_boundary(boundary_type));
            return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
        }
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in get_text_at_offset()" );
    }

    return nullptr;
}

static gunichar
text_wrapper_get_character_at_offset (AtkText          *text,
                                      gint             offset)
{
    gint start, end;
    gunichar uc = 0xFFFFFFFF;

    gchar * char_as_string =
        text_wrapper_get_text_at_offset(text, offset, ATK_TEXT_BOUNDARY_CHAR,
                                        &start, &end);
    if( char_as_string )
    {
        uc = g_utf8_get_char( char_as_string );
        g_free( char_as_string );
    }

    return uc;
}

static gchar *
text_wrapper_get_text_before_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() )
        {
            accessibility::TextSegment aTextSegment = pText->getTextBeforeIndex(offset, text_type_from_boundary(boundary_type));
            return adjust_boundaries(pText, aTextSegment, boundary_type, start_offset, end_offset);
        }
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in text_before_offset()" );
    }

    return nullptr;
}

static gint
text_wrapper_get_caret_offset (AtkText          *text)
{
    gint offset = -1;

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
            offset = pText->getCaretPosition();
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in getCaretPosition()" );
    }

    return offset;
}

static gboolean
text_wrapper_set_caret_offset (AtkText *text,
                               gint     offset)
{
    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
            return pText->setCaretPosition( offset );
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in setCaretPosition()" );
    }

    return FALSE;
}

// #i92232#
static AtkAttributeSet*
handle_text_markup_as_run_attribute( css::uno::Reference<css::accessibility::XAccessibleTextMarkup> const & pTextMarkup,
                                     const gint nTextMarkupType,
                                     const gint offset,
                                     AtkAttributeSet* pSet,
                                     gint *start_offset,
                                     gint *end_offset )
{
    const gint nTextMarkupCount( pTextMarkup->getTextMarkupCount( nTextMarkupType ) );
    for ( gint nTextMarkupIndex = 0;
          nTextMarkupIndex < nTextMarkupCount;
          ++nTextMarkupIndex )
    {
        accessibility::TextSegment aTextSegment =
            pTextMarkup->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
        const gint nStartOffsetTextMarkup = aTextSegment.SegmentStart;
        const gint nEndOffsetTextMarkup = aTextSegment.SegmentEnd;
        if ( nStartOffsetTextMarkup <= offset )
        {
            if ( offset < nEndOffsetTextMarkup )
            {
                // text markup at <offset>
                *start_offset = ::std::max( *start_offset,
                                            nStartOffsetTextMarkup );
                *end_offset = ::std::min( *end_offset,
                                          nEndOffsetTextMarkup );
                switch ( nTextMarkupType )
                {
                    case css::text::TextMarkupType::SPELLCHECK:
                    {
                        pSet = attribute_set_prepend_misspelled( pSet );
                    }
                    break;
                    case css::text::TextMarkupType::TRACK_CHANGE_INSERTION:
                    {
                        pSet = attribute_set_prepend_tracked_change_insertion( pSet );
                    }
                    break;
                    case css::text::TextMarkupType::TRACK_CHANGE_DELETION:
                    {
                        pSet = attribute_set_prepend_tracked_change_deletion( pSet );
                    }
                    break;
                    case css::text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
                    {
                        pSet = attribute_set_prepend_tracked_change_formatchange( pSet );
                    }
                    break;
                    default:
                    {
                        OSL_ASSERT( false );
                    }
                }
                break// no further iteration needed.
            }
            else
            {
                *start_offset = ::std::max( *start_offset,
                                            nEndOffsetTextMarkup );
                // continue iteration.
            }
        }
        else
        {
            *end_offset = ::std::min( *end_offset,
                                      nStartOffsetTextMarkup );
            break// no further iteration.
        }
    }

    return pSet;
}

static AtkAttributeSet *
text_wrapper_get_run_attributes( AtkText        *text,
                                 gint           offset,
                                 gint           *start_offset,
                                 gint           *end_offset)
{
    AtkAttributeSet *pSet = nullptr;

    try {
        bool bOffsetsAreValid = false;

        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is())
        {
            uno::Sequence< beans::PropertyValue > aAttributeList;

            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&){

        g_warning( "Exception in get_run_attributes()" );

        if( pSet )
        {
            atk_attribute_set_free( pSet );
            pSet = nullptr;
        }
    }

    return pSet;
}

/*****************************************************************************/

static AtkAttributeSet *
text_wrapper_get_default_attributes( AtkText *text )
{
    AtkAttributeSet *pSet = nullptr;

    try {
        css::uno::Reference<css::accessibility::XAccessibleTextAttributes>
            pTextAttributes = getTextAttributes( text );
        if( pTextAttributes.is() )
        {
            uno::Sequence< beans::PropertyValue > aAttributeList =
                pTextAttributes->getDefaultAttributes( uno::Sequence< OUString > () );

            pSet = attribute_set_new_from_property_values( aAttributeList, false, text );
        }
    }
    catch(const uno::Exception&) {

        g_warning( "Exception in get_default_attributes()" );

        if( pSet )
        {
            atk_attribute_set_free( pSet );
            pSet = nullptr;
        }
    }

    return pSet;
}

/*****************************************************************************/

static void
text_wrapper_get_character_extents( AtkText          *text,
                                    gint             offset,
                                    gint             *x,
                                    gint             *y,
                                    gint             *width,
                                    gint             *height,
                                    AtkCoordType      coords )
{
    *x = *y = *width = *height = -1;

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
        {
            awt::Rectangle aRect = pText->getCharacterBounds( offset );

            gint origin_x = 0;
            gint origin_y = 0;

            if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
            {
                g_return_if_fail( ATK_IS_COMPONENT( text ) );
                gint nWidth = -1;
                gint nHeight = -1;
                atk_component_get_extents(ATK_COMPONENT(text), &origin_x, &origin_y, &nWidth, &nHeight, coords);
            }

            *x = aRect.X + origin_x;
            *y = aRect.Y + origin_y;
            *width = aRect.Width;
            *height = aRect.Height;
        }
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in getCharacterBounds" );
    }
}

static gint
text_wrapper_get_character_count (AtkText *text)
{
    gint rv = 0;

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
            rv = pText->getCharacterCount();
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in getCharacterCount" );
    }

    return rv;
}

static gint
text_wrapper_get_offset_at_point (AtkText     *text,
                                  gint         x,
                                  gint         y,
                                  AtkCoordType coords)
{
    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
        {
            gint origin_x = 0;
            gint origin_y = 0;

            if (coords == ATK_XY_SCREEN || coords == ATK_XY_WINDOW)
            {
                g_return_val_if_fail( ATK_IS_COMPONENT( text ), -1 );
                gint nWidth = -1;
                gint nHeight = -1;
                atk_component_get_extents(ATK_COMPONENT(text), &origin_x, &origin_y, &nWidth, &nHeight, coords);
            }

            return pText->getIndexAtPoint( awt::Point(x - origin_x, y - origin_y) );
        }
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in getIndexAtPoint" );
    }

    return -1;
}

// FIXME: the whole series of selections API is problematic ...

static gint
text_wrapper_get_n_selections (AtkText *text)
{
    gint rv = 0;

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
            rv = ( pText->getSelectionEnd() > pText->getSelectionStart() ) ? 1 : 0;
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in getSelectionEnd() or getSelectionStart()" );
    }

    return rv;
}

static gchar *
text_wrapper_get_selection (AtkText *text,
                            gint     selection_num,
                            gint    *start_offset,
                            gint    *end_offset)
{
    g_return_val_if_fail( selection_num == 0, FALSE );

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
        {
            *start_offset = pText->getSelectionStart();
            *end_offset   = pText->getSelectionEnd();

            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 ?

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
            return pText->setSelection( start_offset, end_offset ); // ?
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in setSelection()" );
    }

    return FALSE;
}

static gboolean
text_wrapper_remove_selection (AtkText *text,
                               gint     selection_num)
{
    g_return_val_if_fail( selection_num == 0, FALSE );

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> xText = getText(text);
        if (!xText.is())
            return false;

        const sal_Int32 nCaretPos = xText->getCaretPosition();
        return xText->setSelection(nCaretPos, nCaretPos);
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in setSelection()" );
    }

    return FALSE;
}

static gboolean
text_wrapper_set_selection (AtkText *text,
                            gint     selection_num,
                            gint     start_offset,
                            gint     end_offset)
{
    g_return_val_if_fail( selection_num == 0, FALSE );

    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );
        if( pText.is() )
            return pText->setSelection( start_offset, end_offset );
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in setSelection()" );
    }

    return FALSE;
}

#if ATK_CHECK_VERSION(2,32,0)
static gboolean
text_wrapper_scroll_substring_to(AtkText       *text,
                                 gint           start_offset,
                                 gint           end_offset,
                                 AtkScrollType  scroll_type)
{
    try {
        css::uno::Reference<css::accessibility::XAccessibleText> pText
            = getText( text );

        if( pText.is() )
            return pText->scrollSubstringTo( start_offset, end_offset,
                                             scroll_type_from_scroll_type( scroll_type ) );
    }
    catch(const uno::Exception&) {
        g_warning( "Exception in scrollSubstringTo()" );
    }

    return FALSE;
}
#endif

// extern "C"

void
textIfaceInit (gpointer iface_, gpointer)
{
  auto const iface = static_cast<AtkTextIface *>(iface_);
  g_return_if_fail (iface != nullptr);

  iface->get_text = text_wrapper_get_text;
  iface->get_character_at_offset = text_wrapper_get_character_at_offset;
  iface->get_text_before_offset = text_wrapper_get_text_before_offset;
  iface->get_text_at_offset = text_wrapper_get_text_at_offset;
  iface->get_text_after_offset = text_wrapper_get_text_after_offset;
  iface->get_caret_offset = text_wrapper_get_caret_offset;
  iface->set_caret_offset = text_wrapper_set_caret_offset;
  iface->get_character_count = text_wrapper_get_character_count;
  iface->get_n_selections = text_wrapper_get_n_selections;
  iface->get_selection = text_wrapper_get_selection;
  iface->add_selection = text_wrapper_add_selection;
  iface->remove_selection = text_wrapper_remove_selection;
  iface->set_selection = text_wrapper_set_selection;
  iface->get_run_attributes = text_wrapper_get_run_attributes;
  iface->get_default_attributes = text_wrapper_get_default_attributes;
  iface->get_character_extents = text_wrapper_get_character_extents;
  iface->get_offset_at_point = text_wrapper_get_offset_at_point;
#if ATK_CHECK_VERSION(2,32,0)
  iface->scroll_substring_to = text_wrapper_scroll_substring_to;
#endif
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=100 G=97

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.