1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 #include "atktextattributes.hxx"
22 #include <com/sun/star/awt/FontSlant.hpp>
23 #include <com/sun/star/awt/FontStrikeout.hpp>
24 #include <com/sun/star/awt/FontUnderline.hpp>
26 #include <com/sun/star/style/CaseMap.hpp>
27 #include <com/sun/star/style/LineSpacing.hpp>
28 #include <com/sun/star/style/LineSpacingMode.hpp>
29 #include <com/sun/star/style/ParagraphAdjust.hpp>
30 #include <com/sun/star/style/TabAlign.hpp>
31 #include <com/sun/star/style/TabStop.hpp>
33 #include <com/sun/star/text/WritingMode2.hpp>
35 #include "atkwrapper.hxx"
37 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
39 #include <i18nlangtag/languagetag.hxx>
40 #include <tools/UnitConversion.hxx>
41 #include <o3tl/safeint.hxx>
42 #include <o3tl/string_view.hxx>
47 using namespace ::com::sun::star
;
49 typedef gchar
* (* AtkTextAttrFunc
) ( const uno::Any
& rAny
);
50 typedef bool (* TextPropertyValueFunc
) ( uno::Any
& rAny
, const gchar
* value
);
52 #define STRNCMP_PARAM( s ) s,sizeof( s )-1
54 /*****************************************************************************/
56 static AtkTextAttribute atk_text_attribute_paragraph_style
= ATK_TEXT_ATTR_INVALID
;
57 static AtkTextAttribute atk_text_attribute_font_effect
= ATK_TEXT_ATTR_INVALID
;
58 static AtkTextAttribute atk_text_attribute_decoration
= ATK_TEXT_ATTR_INVALID
;
59 static AtkTextAttribute atk_text_attribute_line_height
= ATK_TEXT_ATTR_INVALID
;
60 static AtkTextAttribute atk_text_attribute_rotation
= ATK_TEXT_ATTR_INVALID
;
61 static AtkTextAttribute atk_text_attribute_shadow
= ATK_TEXT_ATTR_INVALID
;
62 static AtkTextAttribute atk_text_attribute_tab_interval
= ATK_TEXT_ATTR_INVALID
;
63 static AtkTextAttribute atk_text_attribute_tab_stops
= ATK_TEXT_ATTR_INVALID
;
64 static AtkTextAttribute atk_text_attribute_writing_mode
= ATK_TEXT_ATTR_INVALID
;
65 static AtkTextAttribute atk_text_attribute_vertical_align
= ATK_TEXT_ATTR_INVALID
;
66 static AtkTextAttribute atk_text_attribute_misspelled
= ATK_TEXT_ATTR_INVALID
;
68 static AtkTextAttribute atk_text_attribute_tracked_change
= ATK_TEXT_ATTR_INVALID
;
70 static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio
= ATK_TEXT_ATTR_INVALID
;
72 /*****************************************************************************/
75 * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
76 * and re-arrange the enum values accordingly.
81 enum ExportedAttribute
83 TEXT_ATTRIBUTE_BACKGROUND_COLOR
= 0,
84 TEXT_ATTRIBUTE_CASEMAP
,
85 TEXT_ATTRIBUTE_FOREGROUND_COLOR
,
86 TEXT_ATTRIBUTE_CONTOURED
,
87 TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
,
88 TEXT_ATTRIBUTE_BLINKING
,
89 TEXT_ATTRIBUTE_FONT_NAME
,
90 TEXT_ATTRIBUTE_HEIGHT
,
91 TEXT_ATTRIBUTE_HIDDEN
,
92 TEXT_ATTRIBUTE_KERNING
,
93 TEXT_ATTRIBUTE_LOCALE
,
94 TEXT_ATTRIBUTE_POSTURE
,
95 TEXT_ATTRIBUTE_RELIEF
,
96 TEXT_ATTRIBUTE_ROTATION
,
98 TEXT_ATTRIBUTE_SHADOWED
,
99 TEXT_ATTRIBUTE_STRIKETHROUGH
,
100 TEXT_ATTRIBUTE_UNDERLINE
,
101 TEXT_ATTRIBUTE_WEIGHT
,
103 TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
,
104 TEXT_ATTRIBUTE_JUSTIFICATION
,
105 TEXT_ATTRIBUTE_BOTTOM_MARGIN
,
106 TEXT_ATTRIBUTE_FIRST_LINE_INDENT
,
107 TEXT_ATTRIBUTE_LEFT_MARGIN
,
108 TEXT_ATTRIBUTE_LINE_SPACING
,
109 TEXT_ATTRIBUTE_RIGHT_MARGIN
,
110 TEXT_ATTRIBUTE_STYLE_NAME
,
111 TEXT_ATTRIBUTE_TAB_STOPS
,
112 TEXT_ATTRIBUTE_TOP_MARGIN
,
113 TEXT_ATTRIBUTE_WRITING_MODE
,
119 static const char * ExportedTextAttributes
[TEXT_ATTRIBUTE_LAST
] =
121 "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
122 "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
123 "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
124 "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
125 "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
126 "CharFlash", // TEXT_ATTRIBUTE_BLINKING
127 "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
128 "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
129 "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
130 "CharKerning", // TEXT_ATTRIBUTE_KERNING
131 "CharLocale", // TEXT_ATTRIBUTE_LOCALE
132 "CharPosture", // TEXT_ATTRIBUTE_POSTURE
133 "CharRelief", // TEXT_ATTRIBUTE_RELIEF
134 "CharRotation", // TEXT_ATTRIBUTE_ROTATION
135 "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
136 "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
137 "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
138 "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
139 "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
141 "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
142 "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
143 "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
144 "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
145 "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
146 "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
147 "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
148 "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
149 "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
150 "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
151 "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
154 /*****************************************************************************/
157 get_value( const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
158 sal_Int32 nIndex
, AtkTextAttrFunc func
)
161 return func(rAttributeList
[nIndex
].Value
);
166 #define get_bool_value( list, index ) get_value( list, index, Bool2String )
167 #define get_height_value( list, index ) get_value( list, index, Float2String )
168 #define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
169 #define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
170 #define get_scale_width( list, index ) get_value( list, index, Scale2String )
171 #define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
172 #define get_string_value( list, index ) get_value( list, index, GetString )
173 #define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
174 #define get_underline_value( list, index ) get_value( list, index, Underline2String )
175 #define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
176 #define get_weight_value( list, index ) get_value( list, index, Weight2String )
177 #define get_language_string( list, index ) get_value( list, index, Locale2String )
179 /*****************************************************************************/
182 InvalidValue( uno::Any
&, const gchar
* )
187 /*****************************************************************************/
190 Float2String(const uno::Any
& rAny
)
192 return g_strdup_printf( "%g", rAny
.get
<float>() );
196 String2Float( uno::Any
& rAny
, const gchar
* value
)
200 if( 1 != sscanf( value
, "%g", &fval
) )
207 /*****************************************************************************/
209 /// @throws uno::RuntimeException
210 static css::uno::Reference
<css::accessibility::XAccessibleComponent
>
211 getComponent( AtkText
*pText
)
213 AtkObjectWrapper
*pWrap
= ATK_OBJECT_WRAPPER( pText
);
216 if( !pWrap
->mpComponent
.is() )
218 pWrap
->mpComponent
.set(pWrap
->mpContext
, css::uno::UNO_QUERY
);
221 return pWrap
->mpComponent
;
224 return css::uno::Reference
<css::accessibility::XAccessibleComponent
>();
228 get_color_value(const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
229 const sal_Int32
* pIndexArray
,
230 ExportedAttribute attr
,
233 sal_Int32 nColor
= -1; // AUTOMATIC
234 sal_Int32 nIndex
= pIndexArray
[attr
];
237 nColor
= rAttributeList
[nIndex
].Value
.get
<sal_Int32
>();
240 * Check for color value for 100% alpha white, which means
241 * "automatic". Grab the RGB value from XAccessibleComponent
245 if( (nColor
== -1) && text
)
249 css::uno::Reference
<css::accessibility::XAccessibleComponent
>
250 pComponent
= getComponent( text
);
251 if( pComponent
.is() )
255 case TEXT_ATTRIBUTE_BACKGROUND_COLOR
:
256 nColor
= pComponent
->getBackground();
258 case TEXT_ATTRIBUTE_FOREGROUND_COLOR
:
259 nColor
= pComponent
->getForeground();
267 catch(const uno::Exception
&) {
268 g_warning( "Exception in get[Fore|Back]groundColor()" );
274 sal_uInt8 blue
= nColor
& 0xFF;
275 sal_uInt8 green
= (nColor
>> 8) & 0xFF;
276 sal_uInt8 red
= (nColor
>> 16) & 0xFF;
278 return g_strdup_printf( "%u,%u,%u", red
, green
, blue
);
285 String2Color( uno::Any
& rAny
, const gchar
* value
)
287 int red
, green
, blue
;
289 if( 3 != sscanf( value
, "%d,%d,%d", &red
, &green
, &blue
) )
292 sal_Int32 nColor
= static_cast<sal_Int32
>(blue
) | ( static_cast<sal_Int32
>(green
) << 8 ) | ( static_cast<sal_Int32
>(red
) << 16 );
297 /*****************************************************************************/
300 FontSlant2Style(const uno::Any
& rAny
)
302 const gchar
* value
= nullptr;
304 awt::FontSlant aFontSlant
;
305 if(!(rAny
>>= aFontSlant
))
310 case awt::FontSlant_NONE
:
314 case awt::FontSlant_OBLIQUE
:
318 case awt::FontSlant_ITALIC
:
322 case awt::FontSlant_REVERSE_OBLIQUE
:
323 value
= "reverse oblique";
326 case awt::FontSlant_REVERSE_ITALIC
:
327 value
= "reverse italic";
335 return g_strdup( value
);
341 Style2FontSlant( uno::Any
& rAny
, const gchar
* value
)
343 awt::FontSlant aFontSlant
;
345 if( strncmp( value
, STRNCMP_PARAM( "normal" ) ) == 0 )
346 aFontSlant
= awt::FontSlant_NONE
;
347 else if( strncmp( value
, STRNCMP_PARAM( "oblique" ) ) == 0 )
348 aFontSlant
= awt::FontSlant_OBLIQUE
;
349 else if( strncmp( value
, STRNCMP_PARAM( "italic" ) ) == 0 )
350 aFontSlant
= awt::FontSlant_ITALIC
;
351 else if( strncmp( value
, STRNCMP_PARAM( "reverse oblique" ) ) == 0 )
352 aFontSlant
= awt::FontSlant_REVERSE_OBLIQUE
;
353 else if( strncmp( value
, STRNCMP_PARAM( "reverse italic" ) ) == 0 )
354 aFontSlant
= awt::FontSlant_REVERSE_ITALIC
;
362 /*****************************************************************************/
365 Weight2String(const uno::Any
& rAny
)
367 return g_strdup_printf( "%g", rAny
.get
<float>() * 4 );
371 String2Weight( uno::Any
& rAny
, const gchar
* value
)
375 if( 1 != sscanf( value
, "%g", &weight
) )
382 /*****************************************************************************/
385 Adjust2Justification(const uno::Any
& rAny
)
387 const gchar
* value
= nullptr;
389 switch( static_cast<style::ParagraphAdjust
>(rAny
.get
<short>()) )
391 case style::ParagraphAdjust_LEFT
:
395 case style::ParagraphAdjust_RIGHT
:
399 case style::ParagraphAdjust_BLOCK
:
400 case style::ParagraphAdjust_STRETCH
:
404 case style::ParagraphAdjust_CENTER
:
413 return g_strdup( value
);
419 Justification2Adjust( uno::Any
& rAny
, const gchar
* value
)
421 style::ParagraphAdjust nParagraphAdjust
;
423 if( strncmp( value
, STRNCMP_PARAM( "left" ) ) == 0 )
424 nParagraphAdjust
= style::ParagraphAdjust_LEFT
;
425 else if( strncmp( value
, STRNCMP_PARAM( "right" ) ) == 0 )
426 nParagraphAdjust
= style::ParagraphAdjust_RIGHT
;
427 else if( strncmp( value
, STRNCMP_PARAM( "fill" ) ) == 0 )
428 nParagraphAdjust
= style::ParagraphAdjust_BLOCK
;
429 else if( strncmp( value
, STRNCMP_PARAM( "center" ) ) == 0 )
430 nParagraphAdjust
= style::ParagraphAdjust_CENTER
;
434 rAny
<<= static_cast<short>(nParagraphAdjust
);
438 /*****************************************************************************/
440 const gchar
* const font_strikethrough
[] = {
441 "none", // FontStrikeout::NONE
442 "single", // FontStrikeout::SINGLE
443 "double", // FontStrikeout::DOUBLE
444 nullptr, // FontStrikeout::DONTKNOW
445 "bold", // FontStrikeout::BOLD
446 "with /", // FontStrikeout::SLASH
447 "with X" // FontStrikeout::X
451 Strikeout2String(const uno::Any
& rAny
)
453 sal_Int16 n
= rAny
.get
<sal_Int16
>();
455 if( n
>= 0 && o3tl::make_unsigned(n
) < SAL_N_ELEMENTS(font_strikethrough
) )
456 return g_strdup( font_strikethrough
[n
] );
462 String2Strikeout( uno::Any
& rAny
, const gchar
* value
)
464 for( sal_Int16 n
=0; n
< sal_Int16(SAL_N_ELEMENTS(font_strikethrough
)); ++n
)
466 if( ( nullptr != font_strikethrough
[n
] ) &&
467 0 == strncmp( value
, font_strikethrough
[n
], strlen( font_strikethrough
[n
] ) ) )
477 /*****************************************************************************/
480 Underline2String(const uno::Any
& rAny
)
482 const gchar
* value
= nullptr;
484 switch( rAny
.get
<sal_Int16
>() )
486 case awt::FontUnderline::NONE
:
490 case awt::FontUnderline::SINGLE
:
494 case awt::FontUnderline::DOUBLE
:
503 return g_strdup( value
);
509 String2Underline( uno::Any
& rAny
, const gchar
* value
)
513 if( strncmp( value
, STRNCMP_PARAM( "none" ) ) == 0 )
514 nUnderline
= awt::FontUnderline::NONE
;
515 else if( strncmp( value
, STRNCMP_PARAM( "single" ) ) == 0 )
516 nUnderline
= awt::FontUnderline::SINGLE
;
517 else if( strncmp( value
, STRNCMP_PARAM( "double" ) ) == 0 )
518 nUnderline
= awt::FontUnderline::DOUBLE
;
526 /*****************************************************************************/
529 GetString(const uno::Any
& rAny
)
531 OString aFontName
= OUStringToOString( rAny
.get
< OUString
> (), RTL_TEXTENCODING_UTF8
);
533 if( !aFontName
.isEmpty() )
534 return g_strdup( aFontName
.getStr() );
540 SetString( uno::Any
& rAny
, const gchar
* value
)
542 OString
aFontName( value
);
544 if( !aFontName
.isEmpty() )
546 rAny
<<= OStringToOUString( aFontName
, RTL_TEXTENCODING_UTF8
);
553 /*****************************************************************************/
555 // @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
559 CMM2UnitString(const uno::Any
& rAny
)
561 double fValue
= rAny
.get
<sal_Int32
>();
562 fValue
= fValue
* 0.01;
564 return g_strdup_printf( "%gmm", fValue
);
568 UnitString2CMM( uno::Any
& rAny
, const gchar
* value
)
570 float fValue
= 0.0; // pb: don't use double here because of warning on linux
572 if( 1 != sscanf( value
, "%gmm", &fValue
) )
575 fValue
= fValue
* 100;
577 rAny
<<= static_cast<sal_Int32
>(fValue
);
581 /*****************************************************************************/
583 static const gchar
* bool_values
[] = { "true", "false" };
586 Bool2String( const uno::Any
& rAny
)
590 if( rAny
.get
<bool>() )
593 return g_strdup( bool_values
[n
] );
597 String2Bool( uno::Any
& rAny
, const gchar
* value
)
601 if( strncmp( value
, STRNCMP_PARAM( "true" ) ) == 0 )
603 else if( strncmp( value
, STRNCMP_PARAM( "false" ) ) == 0 )
612 /*****************************************************************************/
615 Scale2String( const uno::Any
& rAny
)
617 return g_strdup_printf( "%g", static_cast<double>(rAny
.get
< sal_Int16
> ()) / 100 );
621 String2Scale( uno::Any
& rAny
, const gchar
* value
)
625 if( 1 != sscanf( value
, "%lg", &dval
) )
628 rAny
<<= static_cast<sal_Int16
>(dval
* 100);
632 /*****************************************************************************/
635 CaseMap2String( const uno::Any
& rAny
)
639 switch( rAny
.get
<short>() )
641 case style::CaseMap::SMALLCAPS
:
642 value
= "small_caps";
650 return g_strdup(value
);
654 String2CaseMap( uno::Any
& rAny
, const gchar
* value
)
658 if( strncmp( value
, STRNCMP_PARAM( "normal" ) ) == 0 )
659 nCaseMap
= style::CaseMap::NONE
;
660 else if( strncmp( value
, STRNCMP_PARAM( "small_caps" ) ) == 0 )
661 nCaseMap
= style::CaseMap::SMALLCAPS
;
669 /*****************************************************************************/
671 const gchar
* const font_stretch
[] = {
684 Kerning2Stretch(const uno::Any
& rAny
)
686 sal_Int16 n
= rAny
.get
<sal_Int16
>();
689 // No good idea for a mapping - just return the basic info
695 return g_strdup(font_stretch
[i
]);
698 /*****************************************************************************/
701 Locale2String(const uno::Any
& rAny
)
703 /* FIXME-BCP47: support language tags? And why is country lowercase? */
704 lang::Locale aLocale
= rAny
.get
<lang::Locale
> ();
705 LanguageTag
aLanguageTag( aLocale
);
706 return g_strdup_printf( "%s-%s",
707 OUStringToOString( aLanguageTag
.getLanguage(), RTL_TEXTENCODING_ASCII_US
).getStr(),
708 OUStringToOString( aLanguageTag
.getCountry(), RTL_TEXTENCODING_ASCII_US
).toAsciiLowerCase().getStr() );
712 String2Locale( uno::Any
& rAny
, const gchar
* value
)
714 /* FIXME-BCP47: support language tags? */
717 gchar
** str_array
= g_strsplit_set( value
, "-.@", -1 );
718 if( str_array
[0] != nullptr )
722 lang::Locale aLocale
;
724 aLocale
.Language
= OUString::createFromAscii(str_array
[0]);
725 if( str_array
[1] != nullptr )
727 gchar
* country
= g_ascii_strup(str_array
[1], -1);
728 aLocale
.Country
= OUString::createFromAscii(country
);
735 g_strfreev(str_array
);
739 /*****************************************************************************/
741 // @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
742 static const gchar
* relief
[] = { "none", "emboss", "engrave" };
743 const gchar
* const outline
= "outline";
746 get_font_effect(const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
747 sal_Int32 nContourIndex
, sal_Int32 nReliefIndex
)
749 if( nContourIndex
!= -1 )
751 if( rAttributeList
[nContourIndex
].Value
.get
<bool>() )
752 return g_strdup(outline
);
755 if( nReliefIndex
!= -1 )
757 sal_Int16 n
= rAttributeList
[nReliefIndex
].Value
.get
<sal_Int16
>();
759 return g_strdup(relief
[n
]);
765 /*****************************************************************************/
767 // @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
773 DECORATION_UNDERLINE
,
774 DECORATION_LINE_THROUGH
777 static const gchar
* decorations
[] = { "none", "blink", "underline", "line-through" };
780 get_text_decoration(const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
781 sal_Int32 nBlinkIndex
, sal_Int32 nUnderlineIndex
,
782 sal_Int16 nStrikeoutIndex
)
784 gchar
* value_list
[4] = { nullptr, nullptr, nullptr, nullptr };
787 // no property value found
788 if( ( nBlinkIndex
== -1 ) && (nUnderlineIndex
== -1 ) && (nStrikeoutIndex
== -1))
791 if( nBlinkIndex
!= -1 )
793 if( rAttributeList
[nBlinkIndex
].Value
.get
<bool>() )
794 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_BLINK
]);
796 if( nUnderlineIndex
!= -1 )
798 sal_Int16 n
= rAttributeList
[nUnderlineIndex
].Value
.get
<sal_Int16
> ();
799 if( n
!= awt::FontUnderline::NONE
)
800 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_UNDERLINE
]);
802 if( nStrikeoutIndex
!= -1 )
804 sal_Int16 n
= rAttributeList
[nStrikeoutIndex
].Value
.get
<sal_Int16
> ();
805 if( n
!= awt::FontStrikeout::NONE
&& n
!= awt::FontStrikeout::DONTKNOW
)
806 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_LINE_THROUGH
]);
810 value_list
[count
++] = const_cast <gchar
*> (decorations
[DECORATION_NONE
]);
812 return g_strjoinv(" ", value_list
);
815 /*****************************************************************************/
817 // @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
819 static const gchar
* shadow_values
[] = { "none", "black" };
822 Bool2Shadow( const uno::Any
& rAny
)
826 if( rAny
.get
<bool>() )
829 return g_strdup( shadow_values
[n
] );
832 /*****************************************************************************/
835 Short2Degree( const uno::Any
& rAny
)
837 float f
= rAny
.get
<sal_Int16
>() / 10.0;
838 return g_strdup_printf( "%g", f
);
841 /*****************************************************************************/
843 const gchar
* const directions
[] = { "ltr", "rtl", "rtl", "ltr", "none" };
846 WritingMode2Direction( const uno::Any
& rAny
)
848 sal_Int16 n
= rAny
.get
<sal_Int16
>();
850 if( 0 <= n
&& n
<= text::WritingMode2::PAGE
)
851 return g_strdup(directions
[n
]);
856 // @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
858 const gchar
* const writing_modes
[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
860 WritingMode2String( const uno::Any
& rAny
)
862 sal_Int16 n
= rAny
.get
<sal_Int16
>();
864 if( 0 <= n
&& n
<= text::WritingMode2::PAGE
)
865 return g_strdup(writing_modes
[n
]);
870 /*****************************************************************************/
872 const char * const baseline_values
[] = { "baseline", "sub", "super" };
874 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
876 Escapement2VerticalAlign( const uno::Any
& rAny
)
878 sal_Int16 n
= rAny
.get
<sal_Int16
>();
879 gchar
* ret
= nullptr;
881 // Values are in %, 101% means "automatic"
883 ret
= g_strdup(baseline_values
[0]);
885 ret
= g_strdup(baseline_values
[2]);
887 ret
= g_strdup(baseline_values
[1]);
889 ret
= g_strdup_printf( "%d%%", n
);
894 /*****************************************************************************/
896 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
898 LineSpacing2LineHeight( const uno::Any
& rAny
)
900 style::LineSpacing ls
;
901 gchar
* ret
= nullptr;
905 if( ls
.Mode
== style::LineSpacingMode::PROP
)
906 ret
= g_strdup_printf( "%d%%", ls
.Height
);
907 else if( ls
.Mode
== style::LineSpacingMode::FIX
)
908 ret
= g_strdup_printf("%.3gpt", convertMm100ToPoint
<double>(ls
.Height
));
914 /*****************************************************************************/
916 // @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
918 TabStopList2String( const uno::Any
& rAny
, bool default_tabs
)
920 uno::Sequence
< style::TabStop
> theTabStops
;
921 gchar
* ret
= nullptr;
923 if( rAny
>>= theTabStops
)
925 sal_Unicode lastFillChar
= ' ';
927 for (const auto& rTabStop
: theTabStops
)
929 bool is_default_tab
= (style::TabAlign_DEFAULT
== rTabStop
.Alignment
);
931 if( is_default_tab
!= default_tabs
)
934 double fValue
= rTabStop
.Position
;
935 fValue
= fValue
* 0.01;
937 const gchar
* tab_align
= "";
938 switch( rTabStop
.Alignment
)
940 case style::TabAlign_LEFT
:
943 case style::TabAlign_CENTER
:
944 tab_align
= "center ";
946 case style::TabAlign_RIGHT
:
947 tab_align
= "right ";
949 case style::TabAlign_DECIMAL
:
950 tab_align
= "decimal ";
956 const gchar
* lead_char
= "";
958 if( rTabStop
.FillChar
!= lastFillChar
)
960 lastFillChar
= rTabStop
.FillChar
;
961 switch (lastFillChar
)
964 lead_char
= "blank ";
968 lead_char
= "dotted ";
972 lead_char
= "dashed ";
976 lead_char
= "lined ";
980 lead_char
= "custom ";
985 gchar
* tab_str
= g_strdup_printf( "%s%s%gmm", lead_char
, tab_align
, fValue
);
989 gchar
* old_tab_str
= ret
;
990 ret
= g_strconcat(old_tab_str
, " ", tab_str
, nullptr);
992 g_free( old_tab_str
);
1003 TabStops2String( const uno::Any
& rAny
)
1005 return TabStopList2String(rAny
, false);
1009 DefaultTabStops2String( const uno::Any
& rAny
)
1011 return TabStopList2String(rAny
, true);
1014 /*****************************************************************************/
1019 attr_compare(const void *p1
,const void *p2
)
1021 const rtl_uString
* pustr
= static_cast<const rtl_uString
*>(p1
);
1022 const char * pc
= *static_cast<const char * const *>(p2
);
1024 return rtl_ustr_ascii_compare_WithLength(pustr
->buffer
, pustr
->length
, pc
);
1030 find_exported_attributes( sal_Int32
*pArray
,
1031 const css::uno::Sequence
< css::beans::PropertyValue
>& rAttributeList
)
1033 for( sal_Int32 i
= 0; i
< rAttributeList
.getLength(); i
++ )
1035 const char ** pAttr
= static_cast<const char **>(bsearch(rAttributeList
[i
].Name
.pData
,
1036 ExportedTextAttributes
, TEXT_ATTRIBUTE_LAST
, sizeof(const char *),
1041 sal_Int32 nIndex
= pAttr
- ExportedTextAttributes
;
1047 /*****************************************************************************/
1049 static AtkAttributeSet
*
1050 attribute_set_prepend( AtkAttributeSet
* attribute_set
,
1051 AtkTextAttribute attribute
,
1056 AtkAttribute
*at
= static_cast<AtkAttribute
*>(g_malloc( sizeof (AtkAttribute
) ));
1057 at
->name
= g_strdup( atk_text_attribute_get_name( attribute
) );
1060 return g_slist_prepend(attribute_set
, at
);
1063 return attribute_set
;
1066 /*****************************************************************************/
1069 attribute_set_new_from_property_values(
1070 const uno::Sequence
< beans::PropertyValue
>& rAttributeList
,
1071 bool run_attributes_only
,
1074 AtkAttributeSet
* attribute_set
= nullptr;
1076 sal_Int32 aIndexList
[TEXT_ATTRIBUTE_LAST
] = { -1 };
1078 // Initialize index array with -1
1079 for(sal_Int32
& rn
: aIndexList
)
1082 find_exported_attributes(aIndexList
, rAttributeList
);
1084 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_BG_COLOR
,
1085 get_color_value(rAttributeList
, aIndexList
, TEXT_ATTRIBUTE_BACKGROUND_COLOR
, run_attributes_only
? nullptr : text
) );
1087 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_FG_COLOR
,
1088 get_color_value(rAttributeList
, aIndexList
, TEXT_ATTRIBUTE_FOREGROUND_COLOR
, run_attributes_only
? nullptr : text
) );
1090 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_INVISIBLE
,
1091 get_bool_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_HIDDEN
]));
1093 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_UNDERLINE
,
1094 get_underline_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_UNDERLINE
]));
1096 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_STRIKETHROUGH
,
1097 get_strikethrough_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_STRIKETHROUGH
]));
1099 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_SIZE
,
1100 get_height_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_HEIGHT
]));
1102 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_WEIGHT
,
1103 get_weight_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_WEIGHT
]));
1105 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_FAMILY_NAME
,
1106 get_string_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_FONT_NAME
]));
1108 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_VARIANT
,
1109 get_variant_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_CASEMAP
]));
1111 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_STYLE
,
1112 get_style_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_POSTURE
]));
1114 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_SCALE
,
1115 get_scale_width(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_SCALE
]));
1117 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_LANGUAGE
,
1118 get_language_string(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_LOCALE
]));
1120 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_DIRECTION
,
1121 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_WRITING_MODE
], WritingMode2Direction
));
1123 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_STRETCH
,
1124 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_KERNING
], Kerning2Stretch
));
1126 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_font_effect
)
1127 atk_text_attribute_font_effect
= atk_text_attribute_register("font-effect");
1129 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_font_effect
,
1130 get_font_effect(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_CONTOURED
], aIndexList
[TEXT_ATTRIBUTE_RELIEF
]));
1132 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_decoration
)
1133 atk_text_attribute_decoration
= atk_text_attribute_register("text-decoration");
1135 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_decoration
,
1136 get_text_decoration(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_BLINKING
],
1137 aIndexList
[TEXT_ATTRIBUTE_UNDERLINE
], aIndexList
[TEXT_ATTRIBUTE_STRIKETHROUGH
]));
1139 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_rotation
)
1140 atk_text_attribute_rotation
= atk_text_attribute_register("text-rotation");
1142 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_rotation
,
1143 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_ROTATION
], Short2Degree
));
1145 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_shadow
)
1146 atk_text_attribute_shadow
= atk_text_attribute_register("text-shadow");
1148 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_shadow
,
1149 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_SHADOWED
], Bool2Shadow
));
1151 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_writing_mode
)
1152 atk_text_attribute_writing_mode
= atk_text_attribute_register("writing-mode");
1154 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_writing_mode
,
1155 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_WRITING_MODE
], WritingMode2String
));
1157 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_vertical_align
)
1158 atk_text_attribute_vertical_align
= atk_text_attribute_register("vertical-align");
1160 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_vertical_align
,
1161 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
], Escapement2VerticalAlign
));
1163 if( run_attributes_only
)
1164 return attribute_set
;
1166 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_LEFT_MARGIN
,
1167 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_LEFT_MARGIN
]));
1169 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_RIGHT_MARGIN
,
1170 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_RIGHT_MARGIN
]));
1172 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_INDENT
,
1173 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_FIRST_LINE_INDENT
]));
1175 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
,
1176 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_TOP_MARGIN
]));
1178 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_PIXELS_BELOW_LINES
,
1179 get_cmm_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_BOTTOM_MARGIN
]));
1181 attribute_set
= attribute_set_prepend(attribute_set
, ATK_TEXT_ATTR_JUSTIFICATION
,
1182 get_justification_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_JUSTIFICATION
]));
1184 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_paragraph_style
)
1185 atk_text_attribute_paragraph_style
= atk_text_attribute_register("paragraph-style");
1187 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_paragraph_style
,
1188 get_string_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_STYLE_NAME
]));
1190 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_line_height
)
1191 atk_text_attribute_line_height
= atk_text_attribute_register("line-height");
1193 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_line_height
,
1194 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_LINE_SPACING
], LineSpacing2LineHeight
));
1196 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tab_interval
)
1197 atk_text_attribute_tab_interval
= atk_text_attribute_register("tab-interval");
1199 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_tab_interval
,
1200 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_TAB_STOPS
], DefaultTabStops2String
));
1202 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tab_stops
)
1203 atk_text_attribute_tab_stops
= atk_text_attribute_register("tab-stops");
1205 attribute_set
= attribute_set_prepend(attribute_set
, atk_text_attribute_tab_stops
,
1206 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_TAB_STOPS
], TabStops2String
));
1209 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_mm_to_pixel_ratio
)
1210 atk_text_attribute_mm_to_pixel_ratio
= atk_text_attribute_register("mm-to-pixel-ratio");
1212 attribute_set
= attribute_set_prepend( attribute_set
, atk_text_attribute_mm_to_pixel_ratio
,
1213 get_value(rAttributeList
, aIndexList
[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
], Float2String
));
1215 return attribute_set
;
1219 attribute_set_new_from_extended_attributes(
1220 const css::uno::Reference
< css::accessibility::XAccessibleExtendedAttributes
>& rExtendedAttributes
)
1222 AtkAttributeSet
*pSet
= nullptr;
1224 // extended attributes is a string of colon-separated pairs of property and value,
1225 // with pairs separated by semicolons. Example: "heading-level:2;weight:bold;"
1226 uno::Any anyVal
= rExtendedAttributes
->getExtendedAttributes();
1227 OUString sExtendedAttrs
;
1228 anyVal
>>= sExtendedAttrs
;
1229 sal_Int32 nIndex
= 0;
1232 OUString sProperty
= sExtendedAttrs
.getToken( 0, ';', nIndex
);
1234 sal_Int32 nColonPos
= 0;
1235 OString sPropertyName
= OUStringToOString( o3tl::getToken(sProperty
, 0, ':', nColonPos
),
1236 RTL_TEXTENCODING_UTF8
);
1237 OString sPropertyValue
= OUStringToOString( o3tl::getToken(sProperty
, 0, ':', nColonPos
),
1238 RTL_TEXTENCODING_UTF8
);
1240 pSet
= attribute_set_prepend( pSet
,
1241 atk_text_attribute_register( sPropertyName
.getStr() ),
1242 g_strdup_printf( "%s", sPropertyValue
.getStr() ) );
1244 while ( nIndex
>= 0 && nIndex
< sExtendedAttrs
.getLength() );
1249 AtkAttributeSet
* attribute_set_prepend_misspelled( AtkAttributeSet
* attribute_set
)
1251 if( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_misspelled
)
1252 atk_text_attribute_misspelled
= atk_text_attribute_register( "text-spelling" );
1254 attribute_set
= attribute_set_prepend( attribute_set
, atk_text_attribute_misspelled
,
1255 g_strdup_printf( "misspelled" ) );
1257 return attribute_set
;
1261 AtkAttributeSet
* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet
* attribute_set
)
1263 if ( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tracked_change
)
1265 atk_text_attribute_tracked_change
= atk_text_attribute_register( "text-tracked-change" );
1268 attribute_set
= attribute_set_prepend( attribute_set
,
1269 atk_text_attribute_tracked_change
,
1270 g_strdup_printf( "insertion" ) );
1272 return attribute_set
;
1275 AtkAttributeSet
* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet
* attribute_set
)
1277 if ( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tracked_change
)
1279 atk_text_attribute_tracked_change
= atk_text_attribute_register( "text-tracked-change" );
1282 attribute_set
= attribute_set_prepend( attribute_set
,
1283 atk_text_attribute_tracked_change
,
1284 g_strdup_printf( "deletion" ) );
1286 return attribute_set
;
1289 AtkAttributeSet
* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet
* attribute_set
)
1291 if ( ATK_TEXT_ATTR_INVALID
== atk_text_attribute_tracked_change
)
1293 atk_text_attribute_tracked_change
= atk_text_attribute_register( "text-tracked-change" );
1296 attribute_set
= attribute_set_prepend( attribute_set
,
1297 atk_text_attribute_tracked_change
,
1298 g_strdup_printf( "attribute-change" ) );
1300 return attribute_set
;
1303 /*****************************************************************************/
1307 struct AtkTextAttrMapping
1310 TextPropertyValueFunc toPropertyValue
;
1315 constexpr AtkTextAttrMapping g_TextAttrMap
[]
1317 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_INVALID = 0
1318 { u
"ParaLeftMargin"_ustr
, UnitString2CMM
}, // ATK_TEXT_ATTR_LEFT_MARGIN
1319 { u
"ParaRightMargin"_ustr
, UnitString2CMM
}, // ATK_TEXT_ATTR_RIGHT_MARGIN
1320 { u
"ParaFirstLineIndent"_ustr
, UnitString2CMM
}, // ATK_TEXT_ATTR_INDENT
1321 { u
"CharHidden"_ustr
, String2Bool
}, // ATK_TEXT_ATTR_INVISIBLE
1322 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_EDITABLE
1323 { u
"ParaTopMargin"_ustr
, UnitString2CMM
}, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
1324 { u
"ParaBottomMargin"_ustr
, UnitString2CMM
}, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
1325 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
1326 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
1327 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_RISE
1328 { u
"CharUnderline"_ustr
, String2Underline
}, // ATK_TEXT_ATTR_UNDERLINE
1329 { u
"CharStrikeout"_ustr
, String2Strikeout
}, // ATK_TEXT_ATTR_STRIKETHROUGH
1330 { u
"CharHeight"_ustr
, String2Float
}, // ATK_TEXT_ATTR_SIZE
1331 { u
"CharScaleWidth"_ustr
, String2Scale
}, // ATK_TEXT_ATTR_SCALE
1332 { u
"CharWeight"_ustr
, String2Weight
}, // ATK_TEXT_ATTR_WEIGHT
1333 { u
"CharLocale"_ustr
, String2Locale
}, // ATK_TEXT_ATTR_LANGUAGE
1334 { u
"CharFontName"_ustr
, SetString
}, // ATK_TEXT_ATTR_FAMILY_NAME
1335 { u
"CharBackColor"_ustr
, String2Color
}, // ATK_TEXT_ATTR_BG_COLOR
1336 { u
"CharColor"_ustr
, String2Color
}, // ATK_TEXT_ATTR_FG_COLOR
1337 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_BG_STIPPLE
1338 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_FG_STIPPLE
1339 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_WRAP_MODE
1340 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_DIRECTION
1341 { u
"ParaAdjust"_ustr
, Justification2Adjust
}, // ATK_TEXT_ATTR_JUSTIFICATION
1342 { u
""_ustr
, InvalidValue
}, // ATK_TEXT_ATTR_STRETCH
1343 { u
"CharCaseMap"_ustr
, String2CaseMap
}, // ATK_TEXT_ATTR_VARIANT
1344 { u
"CharPosture"_ustr
, Style2FontSlant
} // ATK_TEXT_ATTR_STYLE
1347 /*****************************************************************************/
1350 attribute_set_map_to_property_values(
1351 AtkAttributeSet
* attribute_set
,
1352 uno::Sequence
< beans::PropertyValue
>& rValueList
)
1354 // Ensure enough space ..
1355 uno::Sequence
< beans::PropertyValue
> aAttributeList (SAL_N_ELEMENTS(g_TextAttrMap
));
1356 auto pAttributeList
= aAttributeList
.getArray();
1358 sal_Int32 nIndex
= 0;
1359 for( GSList
* item
= attribute_set
; item
!= nullptr; item
= g_slist_next( item
) )
1361 AtkAttribute
* attribute
= reinterpret_cast<AtkAttribute
*>(item
);
1363 AtkTextAttribute text_attr
= atk_text_attribute_for_name( attribute
->name
);
1364 if( text_attr
< SAL_N_ELEMENTS(g_TextAttrMap
) )
1366 if( g_TextAttrMap
[text_attr
].name
[0] != '\0' )
1368 if( ! g_TextAttrMap
[text_attr
].toPropertyValue( pAttributeList
[nIndex
].Value
, attribute
->value
) )
1371 pAttributeList
[nIndex
].Name
= g_TextAttrMap
[text_attr
].name
;
1372 pAttributeList
[nIndex
].State
= beans::PropertyState_DIRECT_VALUE
;
1378 // Unsupported text attribute
1383 aAttributeList
.realloc( nIndex
);
1384 rValueList
= std::move(aAttributeList
);
1388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */