update dev300-m58
[ooovba.git] / vcl / unx / gtk / a11y / atktextattributes.cxx
blobd6a119ca3cc3859274726485e3a63001ae367c74
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: atktextattributes.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include "atktextattributes.hxx"
36 #include <com/sun/star/awt/FontSlant.hpp>
37 #include <com/sun/star/awt/FontStrikeout.hpp>
38 #include <com/sun/star/awt/FontUnderline.hpp>
40 #include <com/sun/star/style/CaseMap.hpp>
41 #include <com/sun/star/style/LineSpacing.hpp>
42 #include <com/sun/star/style/LineSpacingMode.hpp>
43 #include <com/sun/star/style/ParagraphAdjust.hpp>
44 #include <com/sun/star/style/TabAlign.hpp>
45 #include <com/sun/star/style/TabStop.hpp>
47 #include <com/sun/star/text/WritingMode2.hpp>
49 #include "atkwrapper.hxx"
51 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
53 #include <vcl/svapp.hxx>
54 #include <vcl/outdev.hxx>
56 #include <stdio.h>
57 #include <string.h>
59 using namespace ::com::sun::star;
61 typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
62 typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
64 #define STRNCMP_PARAM( s ) s,sizeof( s )-1
67 /*****************************************************************************/
69 static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
70 static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
71 static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
72 static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
73 static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
74 static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
75 static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
76 static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
77 static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
78 static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
80 /*****************************************************************************/
82 /**
83 * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
84 * and re-arrange the enum values accordingly.
87 enum ExportedAttribute
89 TEXT_ATTRIBUTE_BACKGROUND_COLOR = 0,
90 TEXT_ATTRIBUTE_CASEMAP,
91 TEXT_ATTRIBUTE_FOREGROUND_COLOR,
92 TEXT_ATTRIBUTE_CONTOURED,
93 TEXT_ATTRIBUTE_CHAR_ESCAPEMENT,
94 TEXT_ATTRIBUTE_BLINKING,
95 TEXT_ATTRIBUTE_FONT_NAME,
96 TEXT_ATTRIBUTE_HEIGHT,
97 TEXT_ATTRIBUTE_HIDDEN,
98 TEXT_ATTRIBUTE_KERNING,
99 TEXT_ATTRIBUTE_LOCALE,
100 TEXT_ATTRIBUTE_POSTURE,
101 TEXT_ATTRIBUTE_RELIEF,
102 TEXT_ATTRIBUTE_ROTATION,
103 TEXT_ATTRIBUTE_SCALE,
104 TEXT_ATTRIBUTE_SHADOWED,
105 TEXT_ATTRIBUTE_STRIKETHROUGH,
106 TEXT_ATTRIBUTE_UNDERLINE,
107 TEXT_ATTRIBUTE_WEIGHT,
108 TEXT_ATTRIBUTE_JUSTIFICATION,
109 TEXT_ATTRIBUTE_BOTTOM_MARGIN,
110 TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
111 TEXT_ATTRIBUTE_LEFT_MARGIN,
112 TEXT_ATTRIBUTE_LINE_SPACING,
113 TEXT_ATTRIBUTE_RIGHT_MARGIN,
114 TEXT_ATTRIBUTE_STYLE_NAME,
115 TEXT_ATTRIBUTE_TAB_STOPS,
116 TEXT_ATTRIBUTE_TOP_MARGIN,
117 TEXT_ATTRIBUTE_WRITING_MODE,
118 TEXT_ATTRIBUTE_LAST
121 static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
123 "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
124 "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
125 "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
126 "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
127 "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
128 "CharFlash", // TEXT_ATTRIBUTE_BLINKING
129 "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
130 "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
131 "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
132 "CharKerning", // TEXT_ATTRIBUTE_KERNING
133 "CharLocale", // TEXT_ATTRIBUTE_LOCALE
134 "CharPosture", // TEXT_ATTRIBUTE_POSTURE
135 "CharRelief", // TEXT_ATTRIBUTE_RELIEF
136 "CharRotation", // TEXT_ATTRIBUTE_ROTATION
137 "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
138 "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
139 "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
140 "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
141 "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
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
155 /*****************************************************************************/
157 static gchar*
158 get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
159 sal_Int32 nIndex, AtkTextAttrFunc func )
161 if( nIndex != -1 )
162 return func(rAttributeList[nIndex].Value);
164 return NULL;
167 #define get_bool_value( list, index ) get_value( list, index, Bool2String )
168 #define get_short_value( list, index ) get_value( list, index, Short2String )
169 //#define get_long_value( list, index ) get_value( list, index, Long2String ) pb: not used (warning on linux)
170 #define get_height_value( list, index ) get_value( list, index, Float2String )
171 #define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
172 #define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
173 #define get_scale_width( list, index ) get_value( list, index, Scale2String )
174 #define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
175 #define get_string_value( list, index ) get_value( list, index, GetString )
176 #define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
177 #define get_underline_value( list, index ) get_value( list, index, Underline2String )
178 #define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
179 #define get_weight_value( list, index ) get_value( list, index, Weight2String )
180 #define get_language_string( list, index ) get_value( list, index, Locale2String )
183 static gchar*
184 dump_value( const uno::Sequence< beans::PropertyValue >& rAttributeList, sal_Int32 nIndex )
186 if( nIndex != -1 )
188 rtl::OString aName = rtl::OUStringToOString(rAttributeList[nIndex].Name, RTL_TEXTENCODING_UTF8);
190 if( rAttributeList[nIndex].Value.has<sal_Int16> () )
191 OSL_TRACE( "%s = %d (short value)", aName.getStr(),
192 rAttributeList[nIndex].Value.get<sal_Int16> () );
194 else if( rAttributeList[nIndex].Value.has<sal_Int8> () )
195 OSL_TRACE( "%s = %d (byte value)", aName.getStr(),
196 rAttributeList[nIndex].Value.get<sal_Int8> () );
198 else if( rAttributeList[nIndex].Value.has<sal_Bool> () )
199 OSL_TRACE( "%s = %s (bool value)", aName.getStr(),
200 rAttributeList[nIndex].Value.get<sal_Bool> () ? "true" : "false" );
202 else if( rAttributeList[nIndex].Value.has<rtl::OUString> () )
203 OSL_TRACE( "%s = %s", aName.getStr(),
204 rtl::OUStringToOString(rAttributeList[nIndex].Value.get<rtl::OUString> (),
205 RTL_TEXTENCODING_UTF8).getStr() );
208 return NULL;
212 static inline
213 double toPoint(sal_Int16 n)
215 // 100th mm -> pt
216 return (double) (n * 72) / 2540;
220 /*****************************************************************************/
223 static gchar*
224 NullString(const uno::Any&)
226 return NULL;
230 static bool
231 InvalidValue( uno::Any&, const gchar * )
233 return false;
236 /*****************************************************************************/
238 static gchar*
239 Float2String(const uno::Any& rAny)
241 return g_strdup_printf( "%g", rAny.get<float>() );
244 static bool
245 String2Float( uno::Any& rAny, const gchar * value )
247 float fval;
249 if( 1 != sscanf( value, "%g", &fval ) )
250 return false;
252 rAny = uno::makeAny( fval );
253 return true;
256 /*****************************************************************************/
259 static gchar*
260 Short2String(const uno::Any& rAny)
262 return g_strdup_printf( "%d", rAny.get<sal_Int16>() );
265 static bool
266 String2Short( uno::Any& rAny, const gchar * value )
268 sal_Int32 lval;
270 if( 1 != sscanf( value, "%d", &lval ) )
271 return false;
273 rAny = uno::makeAny( (sal_Int16) lval );
274 return true;
278 /*****************************************************************************/
279 /* pb: not used (warning on linux)
280 static gchar*
281 Long2String(const uno::Any& rAny)
283 return g_strdup_printf( "%ld", rAny.get<sal_Int32>() );
286 static bool
287 String2Long( uno::Any& rAny, const gchar * value )
289 sal_Int32 lval;
291 if( 1 != sscanf( value, "%ld", &lval ) )
292 return false;
294 rAny = uno::makeAny( lval );
295 return true;
298 /*****************************************************************************/
300 static accessibility::XAccessibleComponent*
301 getComponent( AtkText *pText ) throw (uno::RuntimeException)
303 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
304 if( pWrap )
306 if( !pWrap->mpComponent && pWrap->mpContext )
308 uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleComponent::static_type(NULL) );
309 pWrap->mpComponent = reinterpret_cast< accessibility::XAccessibleComponent * > (any.pReserved);
310 pWrap->mpComponent->acquire();
313 return pWrap->mpComponent;
316 return NULL;
319 static gchar*
320 get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
321 const sal_Int32 * pIndexArray,
322 ExportedAttribute attr,
323 AtkText * text)
325 sal_Int32 nColor = -1; // AUTOMATIC
326 sal_Int32 nIndex = pIndexArray[attr];
328 if( nIndex != -1 )
329 nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
332 * Check for color value for 100% alpha white, which means
333 * "automatic". Grab the RGB value from XAccessibleComponent
334 * in this case.
337 if( (nColor == -1) && text )
341 accessibility::XAccessibleComponent *pComponent = getComponent( text );
342 if( pComponent )
344 switch( attr )
346 case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
347 nColor = pComponent->getBackground();
348 break;
349 case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
350 nColor = pComponent->getForeground();
351 break;
352 default:
353 break;
358 catch(const uno::Exception& e) {
359 g_warning( "Exception in get[Fore|Back]groundColor()" );
363 if( nColor != -1 )
365 sal_uInt8 blue = nColor & 0xFF;
366 sal_uInt8 green = (nColor >> 8) & 0xFF;
367 sal_uInt8 red = (nColor >> 16) & 0xFF;
369 return g_strdup_printf( "%u,%u,%u", red, green, blue );
372 return NULL;
375 static bool
376 String2Color( uno::Any& rAny, const gchar * value )
378 int red, green, blue;
380 if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
381 return false;
383 sal_Int32 nColor = (sal_Int32) blue | ( (sal_Int32) green << 8 ) | ( ( sal_Int32 ) red << 16 );
384 rAny = uno::makeAny( nColor );
385 return true;
388 /*****************************************************************************/
390 static gchar*
391 FontSlant2Style(const uno::Any& rAny)
393 const gchar * value = NULL;
395 switch( rAny.get<awt::FontSlant>() )
397 case awt::FontSlant_NONE:
398 value = "normal";
399 break;
401 case awt::FontSlant_OBLIQUE:
402 value = "oblique";
403 break;
405 case awt::FontSlant_ITALIC:
406 value = "italic";
407 break;
409 case awt::FontSlant_REVERSE_OBLIQUE:
410 value = "reverse oblique";
411 break;
413 case awt::FontSlant_REVERSE_ITALIC:
414 value = "reverse italic";
415 break;
417 default:
418 break;
421 if( value )
422 return g_strdup( value );
424 return NULL;
427 static bool
428 Style2FontSlant( uno::Any& rAny, const gchar * value )
430 awt::FontSlant aFontSlant;
432 if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
433 aFontSlant = awt::FontSlant_NONE;
434 else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) )
435 aFontSlant = awt::FontSlant_OBLIQUE;
436 else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) )
437 aFontSlant = awt::FontSlant_ITALIC;
438 else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) )
439 aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
440 else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) )
441 aFontSlant = awt::FontSlant_REVERSE_ITALIC;
442 else
443 return false;
445 rAny = uno::makeAny( aFontSlant );
446 return true;
449 /*****************************************************************************/
451 static gchar*
452 Weight2String(const uno::Any& rAny)
454 return g_strdup_printf( "%g", rAny.get<float>() * 4 );
457 static bool
458 String2Weight( uno::Any& rAny, const gchar * value )
460 float weight;
462 if( 1 != sscanf( value, "%g", &weight ) )
463 return false;
465 rAny = uno::makeAny( weight / 4 );
466 return true;
470 /*****************************************************************************/
472 static gchar*
473 Adjust2Justification(const uno::Any& rAny)
475 const gchar * value = NULL;
477 switch( rAny.get<short>() )
479 case style::ParagraphAdjust_LEFT:
480 value = "left";
481 break;
483 case style::ParagraphAdjust_RIGHT:
484 value = "right";
485 break;
487 case style::ParagraphAdjust_BLOCK:
488 case style::ParagraphAdjust_STRETCH:
489 value = "fill";
490 break;
492 case style::ParagraphAdjust_CENTER:
493 value = "center";
494 break;
496 default:
497 break;
500 if( value )
501 return g_strdup( value );
503 return NULL;
506 static bool
507 Justification2Adjust( uno::Any& rAny, const gchar * value )
509 short nParagraphAdjust;
511 if( strncmp( value, STRNCMP_PARAM( "left" ) ) )
512 nParagraphAdjust = style::ParagraphAdjust_LEFT;
513 else if( strncmp( value, STRNCMP_PARAM( "right" ) ) )
514 nParagraphAdjust = style::ParagraphAdjust_RIGHT;
515 else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) )
516 nParagraphAdjust = style::ParagraphAdjust_BLOCK;
517 else if( strncmp( value, STRNCMP_PARAM( "center" ) ) )
518 nParagraphAdjust = style::ParagraphAdjust_CENTER;
519 else
520 return false;
522 rAny = uno::makeAny( nParagraphAdjust );
523 return true;
526 /*****************************************************************************/
528 const gchar * font_strikethrough[] = {
529 "none", // FontStrikeout::NONE
530 "single", // FontStrikeout::SINGLE
531 "double", // FontStrikeout::DOUBLE
532 NULL, // FontStrikeout::DONTKNOW
533 "bold", // FontStrikeout::BOLD
534 "with /", // FontStrikeout::SLASH
535 "with X" // FontStrikeout::X
538 const sal_Int16 n_strikeout_constants = sizeof(font_strikethrough) / sizeof(gchar*);
540 static gchar*
541 Strikeout2String(const uno::Any& rAny)
543 sal_Int16 n = rAny.get<sal_Int16>();
545 if( n >= 0 && n < n_strikeout_constants )
546 return g_strdup( font_strikethrough[n] );
548 return NULL;
551 static bool
552 String2Strikeout( uno::Any& rAny, const gchar * value )
554 for( sal_Int16 n=0; n < n_strikeout_constants; ++n )
556 if( ( NULL != font_strikethrough[n] ) &&
557 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
559 rAny = uno::makeAny( n );
560 return true;
564 return false;
567 /*****************************************************************************/
569 static gchar*
570 Underline2String(const uno::Any& rAny)
572 const gchar * value = NULL;
574 switch( rAny.get<sal_Int16>() )
576 case awt::FontUnderline::NONE:
577 value = "none";
578 break;
580 case awt::FontUnderline::SINGLE:
581 value = "single";
582 break;
584 case awt::FontUnderline::DOUBLE:
585 value = "double";
586 break;
588 default:
589 break;
592 if( value )
593 return g_strdup( value );
595 return NULL;
598 static bool
599 String2Underline( uno::Any& rAny, const gchar * value )
601 short nUnderline;
603 if( strncmp( value, STRNCMP_PARAM( "none" ) ) )
604 nUnderline = awt::FontUnderline::NONE;
605 else if( strncmp( value, STRNCMP_PARAM( "single" ) ) )
606 nUnderline = awt::FontUnderline::SINGLE;
607 else if( strncmp( value, STRNCMP_PARAM( "double" ) ) )
608 nUnderline = awt::FontUnderline::DOUBLE;
609 else
610 return false;
612 rAny = uno::makeAny( nUnderline );
613 return true;
616 /*****************************************************************************/
618 static gchar*
619 GetString(const uno::Any& rAny)
621 rtl::OString aFontName = rtl::OUStringToOString( rAny.get< rtl::OUString > (), RTL_TEXTENCODING_UTF8 );
623 if( aFontName.getLength() )
624 return g_strdup( aFontName.getStr() );
626 return NULL;
629 static bool
630 SetString( uno::Any& rAny, const gchar * value )
632 rtl::OString aFontName( value );
634 if( aFontName.getLength() )
636 rAny = uno::makeAny( rtl::OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 ) );
637 return true;
640 return false;
643 /*****************************************************************************/
645 // @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
647 // CMM = 100th of mm
648 static gchar*
649 CMM2UnitString(const uno::Any& rAny)
651 double fValue = rAny.get<sal_Int32>();
652 fValue = fValue * 0.01;
654 return g_strdup_printf( "%gmm", fValue );
657 static bool
658 UnitString2CMM( uno::Any& rAny, const gchar * value )
660 float fValue = 0.0; // pb: dont use double here because of warning on linux
662 if( 1 != sscanf( value, "%gmm", &fValue ) )
663 return false;
665 fValue = fValue * 100;
667 rAny = uno::makeAny( (sal_Int32) fValue);
668 return true;
671 /*****************************************************************************/
673 static const gchar * bool_values[] = { "true", "false" };
675 static gchar *
676 Bool2String( const uno::Any& rAny )
678 int n = 1;
680 if( rAny.get<sal_Bool>() )
681 n = 0;
683 return g_strdup( bool_values[n] );
686 static bool
687 String2Bool( uno::Any& rAny, const gchar * value )
689 sal_Bool bValue;
691 if( strncmp( value, STRNCMP_PARAM( "true" ) ) )
692 bValue = sal_True;
693 else if( strncmp( value, STRNCMP_PARAM( "false" ) ) )
694 bValue = sal_False;
695 else
696 return false;
698 rAny = uno::makeAny(bValue);
699 return true;
702 /*****************************************************************************/
704 static gchar*
705 Scale2String( const uno::Any& rAny )
707 return g_strdup_printf( "%g", (double) (rAny.get< sal_Int16 > ()) / 100 );
710 static bool
711 String2Scale( uno::Any& rAny, const gchar * value )
713 double dval;
715 if( 1 != sscanf( value, "%lg", &dval ) )
716 return false;
718 rAny = uno::makeAny((sal_Int16) (dval * 100));
719 return true;
722 /*****************************************************************************/
724 static gchar *
725 CaseMap2String( const uno::Any& rAny )
727 const gchar * value = NULL;
729 switch( rAny.get<short>() )
731 case style::CaseMap::SMALLCAPS:
732 value = "small_caps";
733 break;
735 default:
736 value = "normal";
737 break;
740 if( value )
741 return g_strdup( value );
743 return NULL;
746 static bool
747 String2CaseMap( uno::Any& rAny, const gchar * value )
749 short nCaseMap;
751 if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
752 nCaseMap = style::CaseMap::NONE;
753 else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) )
754 nCaseMap = style::CaseMap::SMALLCAPS;
755 else
756 return false;
758 rAny = uno::makeAny( nCaseMap );
759 return true;
762 /*****************************************************************************/
764 const gchar * font_stretch[] = {
765 "ultra_condensed",
766 "extra_condensed",
767 "condensed",
768 "semi_condensed",
769 "normal",
770 "semi_expanded",
771 "expanded",
772 "extra_expanded",
773 "ultra_expanded"
776 static gchar*
777 Kerning2Stretch(const uno::Any& rAny)
779 sal_Int16 n = rAny.get<sal_Int16>();
780 int i = 4;
782 // No good idea for a mapping - just return the basic info
783 if( n < 0 )
784 i=2;
785 else if( n > 0 )
786 i=6;
788 return g_strdup(font_stretch[i]);
791 /*****************************************************************************/
793 static gchar*
794 Locale2String(const uno::Any& rAny)
796 lang::Locale aLocale = rAny.get<lang::Locale> ();
797 return g_strdup_printf( "%s-%s",
798 rtl::OUStringToOString( aLocale.Language, RTL_TEXTENCODING_ASCII_US).getStr(),
799 rtl::OUStringToOString( aLocale.Country, RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
802 static bool
803 String2Locale( uno::Any& rAny, const gchar * value )
805 bool ret = false;
807 gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
808 if( str_array[0] != NULL )
810 ret = true;
812 lang::Locale aLocale;
814 aLocale.Language = rtl::OUString::createFromAscii(str_array[0]);
815 if( str_array[1] != NULL )
817 gchar * country = g_ascii_strup(str_array[1], -1);
818 aLocale.Country = rtl::OUString::createFromAscii(country);
819 g_free(country);
822 rAny = uno::makeAny(aLocale);
825 g_strfreev(str_array);
826 return ret;
829 /*****************************************************************************/
831 // @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
832 static const gchar * relief[] = { "none", "emboss", "engrave" };
833 static const gchar * outline = "outline";
835 static gchar *
836 get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
837 sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
839 if( nContourIndex != -1 )
841 if( rAttributeList[nContourIndex].Value.get<sal_Bool>() )
842 return g_strdup(outline);
845 if( nReliefIndex != -1 )
847 sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
848 if( n < 3)
849 return g_strdup(relief[n]);
852 return NULL;
855 /*****************************************************************************/
857 // @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
860 enum
862 DECORATION_NONE = 0,
863 DECORATION_BLINK,
864 DECORATION_UNDERLINE,
865 DECORATION_LINE_THROUGH
869 static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
871 static gchar *
872 get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
873 sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
874 sal_Int16 nStrikeoutIndex)
876 gchar * value_list[4] = { NULL, NULL, NULL, NULL };
877 gint count = 0;
879 // no property value found
880 if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
881 return NULL;
883 if( nBlinkIndex != -1 )
885 if( rAttributeList[nBlinkIndex].Value.get<sal_Bool>() )
886 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
888 if( nUnderlineIndex != -1 )
890 sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
891 if( n != awt::FontUnderline::NONE )
892 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
894 if( nStrikeoutIndex != -1 )
896 sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
897 if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
898 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
901 if( count == 0 )
902 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
904 return g_strjoinv(" ", value_list);
908 /*****************************************************************************/
910 // @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
912 static const gchar * shadow_values[] = { "none", "black" };
914 static gchar *
915 Bool2Shadow( const uno::Any& rAny )
917 int n = 0;
919 if( rAny.get<sal_Bool>() )
920 n = 1;
922 return g_strdup( shadow_values[n] );
925 /*****************************************************************************/
927 static gchar *
928 Short2Degree( const uno::Any& rAny )
930 float f = rAny.get<sal_Int16>() / 10;
931 return g_strdup_printf( "%g", f );
934 /*****************************************************************************/
936 const gchar * directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
938 static gchar *
939 WritingMode2Direction( const uno::Any& rAny )
941 sal_Int16 n = rAny.get<sal_Int16>();
943 if( 0 <= n && n <= text::WritingMode2::PAGE )
944 return g_strdup(directions[n]);
946 return NULL;
949 // @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
951 const gchar * writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
952 static gchar *
953 WritingMode2String( const uno::Any& rAny )
955 sal_Int16 n = rAny.get<sal_Int16>();
957 if( 0 <= n && n <= text::WritingMode2::PAGE )
958 return g_strdup(writing_modes[n]);
960 return NULL;
963 /*****************************************************************************/
965 const char * baseline_values[] = { "baseline", "sub", "super" };
967 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
968 static gchar *
969 Escapement2VerticalAlign( const uno::Any& rAny )
971 sal_Int16 n = rAny.get<sal_Int16>();
972 gchar * ret = NULL;
974 // Values are in %, 101% means "automatic"
975 if( n == 0 )
976 ret = g_strdup(baseline_values[0]);
977 else if( n == 101 )
978 ret = g_strdup(baseline_values[2]);
979 else if( n == -101 )
980 ret = g_strdup(baseline_values[1]);
981 else
982 ret = g_strdup_printf( "%d%%", n );
984 return ret;
987 /*****************************************************************************/
989 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
990 static gchar *
991 LineSpacing2LineHeight( const uno::Any& rAny )
993 style::LineSpacing ls;
994 gchar * ret = NULL;
996 if( rAny >>= ls )
998 if( ls.Mode == style::LineSpacingMode::PROP )
999 ret = g_strdup_printf( "%d%%", ls.Height );
1000 else if( ls.Mode == style::LineSpacingMode::FIX )
1001 ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
1004 return ret;
1007 /*****************************************************************************/
1009 // @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
1010 static gchar *
1011 TabStopList2String( const uno::Any& rAny, bool default_tabs )
1013 uno::Sequence< style::TabStop > theTabStops;
1014 gchar * ret = NULL;
1016 if( rAny >>= theTabStops)
1018 sal_Int32 indexOfTab = 0;
1019 sal_Int32 numberOfTabs = theTabStops.getLength();
1020 sal_Unicode lastFillChar = (sal_Unicode) ' ';
1022 for( ; indexOfTab < numberOfTabs; ++indexOfTab )
1024 bool is_default_tab = (style::TabAlign_DEFAULT == theTabStops[indexOfTab].Alignment);
1026 if( is_default_tab != default_tabs )
1027 continue;
1029 double fValue = theTabStops[indexOfTab].Position;
1030 fValue = fValue * 0.01;
1032 const gchar * tab_align = "";
1033 switch( theTabStops[indexOfTab].Alignment )
1035 case style::TabAlign_LEFT :
1036 tab_align = "left ";
1037 break;
1038 case style::TabAlign_CENTER :
1039 tab_align = "center ";
1040 break;
1041 case style::TabAlign_RIGHT :
1042 tab_align = "right ";
1043 break;
1044 case style::TabAlign_DECIMAL :
1045 tab_align = "decimal ";
1046 break;
1047 default:
1048 break;
1051 const gchar * lead_char = "";
1053 if( theTabStops[indexOfTab].FillChar != lastFillChar )
1055 lastFillChar = theTabStops[indexOfTab].FillChar;
1056 switch (lastFillChar)
1058 case (sal_Unicode) ' ':
1059 lead_char = "blank ";
1060 break;
1062 case (sal_Unicode) '.':
1063 lead_char = "dotted ";
1064 break;
1066 case (sal_Unicode) '-':
1067 lead_char = "dashed ";
1068 break;
1070 case (sal_Unicode) '_':
1071 lead_char = "lined ";
1072 break;
1074 default:
1075 lead_char = "custom ";
1076 break;
1080 gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
1082 if( ret )
1084 gchar * old_tab_str = ret;
1085 ret = g_strconcat(old_tab_str, " ", tab_str, NULL /* terminated */);
1086 g_free( old_tab_str );
1088 else
1089 ret = tab_str;
1093 return ret;
1096 static gchar *
1097 TabStops2String( const uno::Any& rAny )
1099 return TabStopList2String(rAny, false);
1102 static gchar *
1103 DefaultTabStops2String( const uno::Any& rAny )
1105 return TabStopList2String(rAny, true);
1108 /*****************************************************************************/
1110 extern "C" int
1111 attr_compare(const void *p1,const void *p2)
1113 const rtl_uString * pustr = (const rtl_uString *) p1;
1114 const char * pc = *((const char **) p2);
1116 return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
1119 static void
1120 find_exported_attributes( sal_Int32 *pArray,
1121 const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rAttributeList )
1123 for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
1125 const char ** pAttr = (const char **) bsearch(rAttributeList[i].Name.pData,
1126 ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
1127 attr_compare);
1129 if( pAttr )
1131 sal_Int32 nIndex = pAttr - ExportedTextAttributes;
1132 pArray[nIndex] = i;
1137 /*****************************************************************************/
1139 static AtkAttributeSet*
1140 attribute_set_prepend( AtkAttributeSet* attribute_set,
1141 AtkTextAttribute attribute,
1142 gchar * value )
1144 if( value )
1146 AtkAttribute *at = (AtkAttribute *) g_malloc( sizeof (AtkAttribute) );
1147 at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
1148 at->value = value;
1150 return g_slist_prepend(attribute_set, at);
1153 return attribute_set;
1156 /*****************************************************************************/
1158 AtkAttributeSet*
1159 attribute_set_new_from_property_values(
1160 const uno::Sequence< beans::PropertyValue >& rAttributeList,
1161 bool run_attributes_only,
1162 AtkText *text)
1164 AtkAttributeSet* attribute_set = NULL;
1166 sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
1168 // Initialize index array with -1
1169 for( sal_Int32 attr = 0; attr < TEXT_ATTRIBUTE_LAST; ++attr )
1170 aIndexList[attr] = -1;
1172 find_exported_attributes(aIndexList, rAttributeList);
1174 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
1175 get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? NULL : text ) );
1177 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
1178 get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? NULL : text) );
1180 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
1181 get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
1183 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
1184 get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
1186 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
1187 get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1189 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
1190 get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
1192 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
1193 get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
1195 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
1196 get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
1198 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
1199 get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
1201 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
1202 get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
1204 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
1205 get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
1207 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
1208 get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
1210 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
1211 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
1213 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
1214 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
1216 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
1217 atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
1219 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
1220 get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
1222 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
1223 atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
1225 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
1226 get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
1227 aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1229 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
1230 atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
1232 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
1233 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
1235 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
1236 atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
1238 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
1239 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
1241 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
1242 atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
1244 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
1245 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
1247 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
1248 atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
1250 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
1251 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
1253 if( run_attributes_only )
1254 return attribute_set;
1256 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
1257 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
1259 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
1260 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
1262 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
1263 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
1265 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
1266 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
1268 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
1269 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
1271 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
1272 get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
1274 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
1275 atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
1277 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
1278 get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
1280 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
1281 atk_text_attribute_line_height = atk_text_attribute_register("line-height");
1283 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
1284 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
1286 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
1287 atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
1289 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
1290 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
1292 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
1293 atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
1295 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
1296 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
1298 return attribute_set;
1302 /*****************************************************************************/
1304 struct AtkTextAttrMapping
1306 const char * name;
1307 TextPropertyValueFunc toPropertyValue;
1310 const AtkTextAttrMapping g_TextAttrMap[] =
1312 { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
1313 { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
1314 { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
1315 { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
1316 { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
1317 { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
1318 { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
1319 { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
1320 { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
1321 { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
1322 { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
1323 { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
1324 { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
1325 { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
1326 { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
1327 { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
1328 { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
1329 { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
1330 { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
1331 { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
1332 { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
1333 { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
1334 { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
1335 { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
1336 { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
1337 { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
1338 { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
1339 { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
1342 static const sal_Int32 g_TextAttrMapSize = sizeof( g_TextAttrMap ) / sizeof( AtkTextAttrMapping );
1344 /*****************************************************************************/
1346 bool
1347 attribute_set_map_to_property_values(
1348 AtkAttributeSet* attribute_set,
1349 uno::Sequence< beans::PropertyValue >& rValueList )
1351 // Ensure enough space ..
1352 uno::Sequence< beans::PropertyValue > aAttributeList (g_TextAttrMapSize);
1354 sal_Int32 nIndex = 0;
1355 for( GSList * item = attribute_set; item != NULL; item = g_slist_next( item ) )
1357 AtkAttribute* attribute = (AtkAttribute *) item;
1359 AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
1360 if( text_attr < g_TextAttrMapSize )
1362 if( g_TextAttrMap[text_attr].name[0] != '\0' )
1364 if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
1365 return false;
1367 aAttributeList[nIndex].Name = rtl::OUString::createFromAscii( g_TextAttrMap[text_attr].name );
1368 aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
1369 ++nIndex;
1372 else
1374 // Unsupported text attribute
1375 return false;
1379 aAttributeList.realloc( nIndex );
1380 rValueList = aAttributeList;
1381 return true;