1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26
27 #include "atktextattributes.hxx"
28
29 #include <com/sun/star/awt/FontSlant.hpp>
30 #include <com/sun/star/awt/FontStrikeout.hpp>
31 #include <com/sun/star/awt/FontUnderline.hpp>
32
33 #include <com/sun/star/style/CaseMap.hpp>
34 #include <com/sun/star/style/LineSpacing.hpp>
35 #include <com/sun/star/style/LineSpacingMode.hpp>
36 #include <com/sun/star/style/ParagraphAdjust.hpp>
37 #include <com/sun/star/style/TabAlign.hpp>
38 #include <com/sun/star/style/TabStop.hpp>
39
40 #include <com/sun/star/text/WritingMode2.hpp>
41
42 #include "atkwrapper.hxx"
43
44 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
45
46 #include <vcl/svapp.hxx>
47 #include <vcl/outdev.hxx>
48
49 #include <stdio.h>
50 #include <string.h>
51
52 using namespace ::com::sun::star;
53
54 typedef gchar* (* AtkTextAttrFunc) ( const uno::Any& rAny );
55 typedef bool (* TextPropertyValueFunc) ( uno::Any& rAny, const gchar * value );
56
57 #define STRNCMP_PARAM( s ) s,sizeof( s )-1
58
59
60 /*****************************************************************************/
61
62 static AtkTextAttribute atk_text_attribute_paragraph_style = ATK_TEXT_ATTR_INVALID;
63 static AtkTextAttribute atk_text_attribute_font_effect = ATK_TEXT_ATTR_INVALID;
64 static AtkTextAttribute atk_text_attribute_decoration = ATK_TEXT_ATTR_INVALID;
65 static AtkTextAttribute atk_text_attribute_line_height = ATK_TEXT_ATTR_INVALID;
66 static AtkTextAttribute atk_text_attribute_rotation = ATK_TEXT_ATTR_INVALID;
67 static AtkTextAttribute atk_text_attribute_shadow = ATK_TEXT_ATTR_INVALID;
68 static AtkTextAttribute atk_text_attribute_tab_interval = ATK_TEXT_ATTR_INVALID;
69 static AtkTextAttribute atk_text_attribute_tab_stops = ATK_TEXT_ATTR_INVALID;
70 static AtkTextAttribute atk_text_attribute_writing_mode = ATK_TEXT_ATTR_INVALID;
71 static AtkTextAttribute atk_text_attribute_vertical_align = ATK_TEXT_ATTR_INVALID;
72 static AtkTextAttribute atk_text_attribute_misspelled = ATK_TEXT_ATTR_INVALID;
73 // --> OD 2010-03-01 #i92232#
74 static AtkTextAttribute atk_text_attribute_tracked_change = ATK_TEXT_ATTR_INVALID;
75 // <--
76 // --> OD 2010-03-05 #i92233#
77 static AtkTextAttribute atk_text_attribute_mm_to_pixel_ratio = ATK_TEXT_ATTR_INVALID;
78 // <--
79
80 /*****************************************************************************/
81
82 /**
83 * !! IMPORTANT NOTE !! : when adding items to this list, KEEP THE LIST SORTED
84 * and re-arrange the enum values accordingly.
85 */
86
87 enum ExportedAttribute
88 {
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 // --> OD 2010-03-05 #i92233#
109 TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO,
110 // <--
111 TEXT_ATTRIBUTE_JUSTIFICATION,
112 TEXT_ATTRIBUTE_BOTTOM_MARGIN,
113 TEXT_ATTRIBUTE_FIRST_LINE_INDENT,
114 TEXT_ATTRIBUTE_LEFT_MARGIN,
115 TEXT_ATTRIBUTE_LINE_SPACING,
116 TEXT_ATTRIBUTE_RIGHT_MARGIN,
117 TEXT_ATTRIBUTE_STYLE_NAME,
118 TEXT_ATTRIBUTE_TAB_STOPS,
119 TEXT_ATTRIBUTE_TOP_MARGIN,
120 TEXT_ATTRIBUTE_WRITING_MODE,
121 TEXT_ATTRIBUTE_LAST
122 };
123
124 static const char * ExportedTextAttributes[TEXT_ATTRIBUTE_LAST] =
125 {
126 "CharBackColor", // TEXT_ATTRIBUTE_BACKGROUND_COLOR
127 "CharCaseMap", // TEXT_ATTRIBUTE_CASEMAP
128 "CharColor", // TEXT_ATTRIBUTE_FOREGROUND_COLOR
129 "CharContoured", // TEXT_ATTRIBUTE_CONTOURED
130 "CharEscapement", // TEXT_ATTRIBUTE_CHAR_ESCAPEMENT
131 "CharFlash", // TEXT_ATTRIBUTE_BLINKING
132 "CharFontName", // TEXT_ATTRIBUTE_FONT_NAME
133 "CharHeight", // TEXT_ATTRIBUTE_HEIGHT
134 "CharHidden", // TEXT_ATTRIBUTE_HIDDEN
135 "CharKerning", // TEXT_ATTRIBUTE_KERNING
136 "CharLocale", // TEXT_ATTRIBUTE_LOCALE
137 "CharPosture", // TEXT_ATTRIBUTE_POSTURE
138 "CharRelief", // TEXT_ATTRIBUTE_RELIEF
139 "CharRotation", // TEXT_ATTRIBUTE_ROTATION
140 "CharScaleWidth", // TEXT_ATTRIBUTE_SCALE
141 "CharShadowed", // TEXT_ATTRIBUTE_SHADOWED
142 "CharStrikeout", // TEXT_ATTRIBUTE_STRIKETHROUGH
143 "CharUnderline", // TEXT_ATTRIBUTE_UNDERLINE
144 "CharWeight", // TEXT_ATTRIBUTE_WEIGHT
145 // --> OD 2010-03-05 #i92233#
146 "MMToPixelRatio", // TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO
147 // <--
148 "ParaAdjust", // TEXT_ATTRIBUTE_JUSTIFICATION
149 "ParaBottomMargin", // TEXT_ATTRIBUTE_BOTTOM_MARGIN
150 "ParaFirstLineIndent", // TEXT_ATTRIBUTE_FIRST_LINE_INDENT
151 "ParaLeftMargin", // TEXT_ATTRIBUTE_LEFT_MARGIN
152 "ParaLineSpacing", // TEXT_ATTRIBUTE_LINE_SPACING
153 "ParaRightMargin", // TEXT_ATTRIBUTE_RIGHT_MARGIN
154 "ParaStyleName", // TEXT_ATTRIBUTE_STYLE_NAME
155 "ParaTabStops", // TEXT_ATTRIBUTE_TAB_STOPS
156 "ParaTopMargin", // TEXT_ATTRIBUTE_TOP_MARGIN
157 "WritingMode" // TEXT_ATTRIBUTE_WRITING_MODE
158 };
159
160
161 /*****************************************************************************/
162
163 static gchar*
get_value(const uno::Sequence<beans::PropertyValue> & rAttributeList,sal_Int32 nIndex,AtkTextAttrFunc func)164 get_value( const uno::Sequence< beans::PropertyValue >& rAttributeList,
165 sal_Int32 nIndex, AtkTextAttrFunc func )
166 {
167 if( nIndex != -1 )
168 return func(rAttributeList[nIndex].Value);
169
170 return NULL;
171 }
172
173 #define get_bool_value( list, index ) get_value( list, index, Bool2String )
174 #define get_short_value( list, index ) get_value( list, index, Short2String )
175 //#define get_long_value( list, index ) get_value( list, index, Long2String ) pb: not used (warning on linux)
176 #define get_height_value( list, index ) get_value( list, index, Float2String )
177 #define get_justification_value( list, index ) get_value( list, index, Adjust2Justification )
178 #define get_cmm_value( list, index ) get_value( list, index, CMM2UnitString )
179 #define get_scale_width( list, index ) get_value( list, index, Scale2String )
180 #define get_strikethrough_value( list, index ) get_value( list, index, Strikeout2String )
181 #define get_string_value( list, index ) get_value( list, index, GetString )
182 #define get_style_value( list, index ) get_value( list, index, FontSlant2Style )
183 #define get_underline_value( list, index ) get_value( list, index, Underline2String )
184 #define get_variant_value( list, index ) get_value( list, index, CaseMap2String )
185 #define get_weight_value( list, index ) get_value( list, index, Weight2String )
186 #define get_language_string( list, index ) get_value( list, index, Locale2String )
187
188 /*
189 static gchar*
190 dump_value( const uno::Sequence< beans::PropertyValue >& rAttributeList, sal_Int32 nIndex )
191 {
192 if( nIndex != -1 )
193 {
194 rtl::OString aName = rtl::OUStringToOString(rAttributeList[nIndex].Name, RTL_TEXTENCODING_UTF8);
195
196 if( rAttributeList[nIndex].Value.has<sal_Int16> () )
197 OSL_TRACE( "%s = %d (short value)", aName.getStr(),
198 rAttributeList[nIndex].Value.get<sal_Int16> () );
199
200 else if( rAttributeList[nIndex].Value.has<sal_Int8> () )
201 OSL_TRACE( "%s = %d (byte value)", aName.getStr(),
202 rAttributeList[nIndex].Value.get<sal_Int8> () );
203
204 else if( rAttributeList[nIndex].Value.has<sal_Bool> () )
205 OSL_TRACE( "%s = %s (bool value)", aName.getStr(),
206 rAttributeList[nIndex].Value.get<sal_Bool> () ? "true" : "false" );
207
208 else if( rAttributeList[nIndex].Value.has<rtl::OUString> () )
209 OSL_TRACE( "%s = %s", aName.getStr(),
210 rtl::OUStringToOString(rAttributeList[nIndex].Value.get<rtl::OUString> (),
211 RTL_TEXTENCODING_UTF8).getStr() );
212 }
213
214 return NULL;
215 }
216 */
217
218 static inline
toPoint(sal_Int16 n)219 double toPoint(sal_Int16 n)
220 {
221 // 100th mm -> pt
222 return (double) (n * 72) / 2540;
223 }
224
225
226 /*****************************************************************************/
227
228 /*
229 static gchar*
230 NullString(const uno::Any&)
231 {
232 return NULL;
233 }
234 */
235
236 static bool
InvalidValue(uno::Any &,const gchar *)237 InvalidValue( uno::Any&, const gchar * )
238 {
239 return false;
240 }
241
242 /*****************************************************************************/
243
244 static gchar*
Float2String(const uno::Any & rAny)245 Float2String(const uno::Any& rAny)
246 {
247 return g_strdup_printf( "%g", rAny.get<float>() );
248 }
249
250 static bool
String2Float(uno::Any & rAny,const gchar * value)251 String2Float( uno::Any& rAny, const gchar * value )
252 {
253 float fval;
254
255 if( 1 != sscanf( value, "%g", &fval ) )
256 return false;
257
258 rAny = uno::makeAny( fval );
259 return true;
260 }
261
262 /*****************************************************************************/
263
264 /*
265 static gchar*
266 Short2String(const uno::Any& rAny)
267 {
268 return g_strdup_printf( "%d", rAny.get<sal_Int16>() );
269 }
270
271 static bool
272 String2Short( uno::Any& rAny, const gchar * value )
273 {
274 sal_Int32 lval;
275
276 if( 1 != sscanf( value, "%d", &lval ) )
277 return false;
278
279 rAny = uno::makeAny( (sal_Int16) lval );
280 return true;
281 }
282 */
283
284 /*****************************************************************************/
285 /* pb: not used (warning on linux)
286 static gchar*
287 Long2String(const uno::Any& rAny)
288 {
289 return g_strdup_printf( "%ld", rAny.get<sal_Int32>() );
290 }
291
292 static bool
293 String2Long( uno::Any& rAny, const gchar * value )
294 {
295 sal_Int32 lval;
296
297 if( 1 != sscanf( value, "%ld", &lval ) )
298 return false;
299
300 rAny = uno::makeAny( lval );
301 return true;
302 }
303 */
304 /*****************************************************************************/
305
306 static accessibility::XAccessibleComponent*
getComponent(AtkText * pText)307 getComponent( AtkText *pText ) throw (uno::RuntimeException)
308 {
309 AtkObjectWrapper *pWrap = ATK_OBJECT_WRAPPER( pText );
310 if( pWrap )
311 {
312 if( !pWrap->mpComponent && pWrap->mpContext )
313 {
314 uno::Any any = pWrap->mpContext->queryInterface( accessibility::XAccessibleComponent::static_type(NULL) );
315 pWrap->mpComponent = reinterpret_cast< accessibility::XAccessibleComponent * > (any.pReserved);
316 pWrap->mpComponent->acquire();
317 }
318
319 return pWrap->mpComponent;
320 }
321
322 return NULL;
323 }
324
325 static gchar*
get_color_value(const uno::Sequence<beans::PropertyValue> & rAttributeList,const sal_Int32 * pIndexArray,ExportedAttribute attr,AtkText * text)326 get_color_value(const uno::Sequence< beans::PropertyValue >& rAttributeList,
327 const sal_Int32 * pIndexArray,
328 ExportedAttribute attr,
329 AtkText * text)
330 {
331 sal_Int32 nColor = -1; // AUTOMATIC
332 sal_Int32 nIndex = pIndexArray[attr];
333
334 if( nIndex != -1 )
335 nColor = rAttributeList[nIndex].Value.get<sal_Int32>();
336
337 /*
338 * Check for color value for 100% alpha white, which means
339 * "automatic". Grab the RGB value from XAccessibleComponent
340 * in this case.
341 */
342
343 if( (nColor == -1) && text )
344 {
345 try
346 {
347 accessibility::XAccessibleComponent *pComponent = getComponent( text );
348 if( pComponent )
349 {
350 switch( attr )
351 {
352 case TEXT_ATTRIBUTE_BACKGROUND_COLOR:
353 nColor = pComponent->getBackground();
354 break;
355 case TEXT_ATTRIBUTE_FOREGROUND_COLOR:
356 nColor = pComponent->getForeground();
357 break;
358 default:
359 break;
360 }
361 }
362 }
363
364 catch(const uno::Exception& e) {
365 g_warning( "Exception in get[Fore|Back]groundColor()" );
366 }
367 }
368
369 if( nColor != -1 )
370 {
371 sal_uInt8 blue = nColor & 0xFF;
372 sal_uInt8 green = (nColor >> 8) & 0xFF;
373 sal_uInt8 red = (nColor >> 16) & 0xFF;
374
375 return g_strdup_printf( "%u,%u,%u", red, green, blue );
376 }
377
378 return NULL;
379 }
380
381 static bool
String2Color(uno::Any & rAny,const gchar * value)382 String2Color( uno::Any& rAny, const gchar * value )
383 {
384 int red, green, blue;
385
386 if( 3 != sscanf( value, "%d,%d,%d", &red, &green, &blue ) )
387 return false;
388
389 sal_Int32 nColor = (sal_Int32) blue | ( (sal_Int32) green << 8 ) | ( ( sal_Int32 ) red << 16 );
390 rAny = uno::makeAny( nColor );
391 return true;
392 }
393
394 /*****************************************************************************/
395
396 static gchar*
FontSlant2Style(const uno::Any & rAny)397 FontSlant2Style(const uno::Any& rAny)
398 {
399 const gchar * value = NULL;
400
401 switch( rAny.get<awt::FontSlant>() )
402 {
403 case awt::FontSlant_NONE:
404 value = "normal";
405 break;
406
407 case awt::FontSlant_OBLIQUE:
408 value = "oblique";
409 break;
410
411 case awt::FontSlant_ITALIC:
412 value = "italic";
413 break;
414
415 case awt::FontSlant_REVERSE_OBLIQUE:
416 value = "reverse oblique";
417 break;
418
419 case awt::FontSlant_REVERSE_ITALIC:
420 value = "reverse italic";
421 break;
422
423 default:
424 break;
425 }
426
427 if( value )
428 return g_strdup( value );
429
430 return NULL;
431 }
432
433 static bool
Style2FontSlant(uno::Any & rAny,const gchar * value)434 Style2FontSlant( uno::Any& rAny, const gchar * value )
435 {
436 awt::FontSlant aFontSlant;
437
438 if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
439 aFontSlant = awt::FontSlant_NONE;
440 else if( strncmp( value, STRNCMP_PARAM( "oblique" ) ) )
441 aFontSlant = awt::FontSlant_OBLIQUE;
442 else if( strncmp( value, STRNCMP_PARAM( "italic" ) ) )
443 aFontSlant = awt::FontSlant_ITALIC;
444 else if( strncmp( value, STRNCMP_PARAM( "reverse oblique" ) ) )
445 aFontSlant = awt::FontSlant_REVERSE_OBLIQUE;
446 else if( strncmp( value, STRNCMP_PARAM( "reverse italic" ) ) )
447 aFontSlant = awt::FontSlant_REVERSE_ITALIC;
448 else
449 return false;
450
451 rAny = uno::makeAny( aFontSlant );
452 return true;
453 }
454
455 /*****************************************************************************/
456
457 static gchar*
Weight2String(const uno::Any & rAny)458 Weight2String(const uno::Any& rAny)
459 {
460 return g_strdup_printf( "%g", rAny.get<float>() * 4 );
461 }
462
463 static bool
String2Weight(uno::Any & rAny,const gchar * value)464 String2Weight( uno::Any& rAny, const gchar * value )
465 {
466 float weight;
467
468 if( 1 != sscanf( value, "%g", &weight ) )
469 return false;
470
471 rAny = uno::makeAny( weight / 4 );
472 return true;
473 }
474
475
476 /*****************************************************************************/
477
478 static gchar*
Adjust2Justification(const uno::Any & rAny)479 Adjust2Justification(const uno::Any& rAny)
480 {
481 const gchar * value = NULL;
482
483 switch( rAny.get<short>() )
484 {
485 case style::ParagraphAdjust_LEFT:
486 value = "left";
487 break;
488
489 case style::ParagraphAdjust_RIGHT:
490 value = "right";
491 break;
492
493 case style::ParagraphAdjust_BLOCK:
494 case style::ParagraphAdjust_STRETCH:
495 value = "fill";
496 break;
497
498 case style::ParagraphAdjust_CENTER:
499 value = "center";
500 break;
501
502 default:
503 break;
504 }
505
506 if( value )
507 return g_strdup( value );
508
509 return NULL;
510 }
511
512 static bool
Justification2Adjust(uno::Any & rAny,const gchar * value)513 Justification2Adjust( uno::Any& rAny, const gchar * value )
514 {
515 short nParagraphAdjust;
516
517 if( strncmp( value, STRNCMP_PARAM( "left" ) ) )
518 nParagraphAdjust = style::ParagraphAdjust_LEFT;
519 else if( strncmp( value, STRNCMP_PARAM( "right" ) ) )
520 nParagraphAdjust = style::ParagraphAdjust_RIGHT;
521 else if( strncmp( value, STRNCMP_PARAM( "fill" ) ) )
522 nParagraphAdjust = style::ParagraphAdjust_BLOCK;
523 else if( strncmp( value, STRNCMP_PARAM( "center" ) ) )
524 nParagraphAdjust = style::ParagraphAdjust_CENTER;
525 else
526 return false;
527
528 rAny = uno::makeAny( nParagraphAdjust );
529 return true;
530 }
531
532 /*****************************************************************************/
533
534 const gchar * font_strikethrough[] = {
535 "none", // FontStrikeout::NONE
536 "single", // FontStrikeout::SINGLE
537 "double", // FontStrikeout::DOUBLE
538 NULL, // FontStrikeout::DONTKNOW
539 "bold", // FontStrikeout::BOLD
540 "with /", // FontStrikeout::SLASH
541 "with X" // FontStrikeout::X
542 };
543
544 const sal_Int16 n_strikeout_constants = sizeof(font_strikethrough) / sizeof(gchar*);
545
546 static gchar*
Strikeout2String(const uno::Any & rAny)547 Strikeout2String(const uno::Any& rAny)
548 {
549 sal_Int16 n = rAny.get<sal_Int16>();
550
551 if( n >= 0 && n < n_strikeout_constants )
552 return g_strdup( font_strikethrough[n] );
553
554 return NULL;
555 }
556
557 static bool
String2Strikeout(uno::Any & rAny,const gchar * value)558 String2Strikeout( uno::Any& rAny, const gchar * value )
559 {
560 for( sal_Int16 n=0; n < n_strikeout_constants; ++n )
561 {
562 if( ( NULL != font_strikethrough[n] ) &&
563 0 == strncmp( value, font_strikethrough[n], strlen( font_strikethrough[n] ) ) )
564 {
565 rAny = uno::makeAny( n );
566 return true;
567 }
568 }
569
570 return false;
571 }
572
573 /*****************************************************************************/
574
575 static gchar*
Underline2String(const uno::Any & rAny)576 Underline2String(const uno::Any& rAny)
577 {
578 const gchar * value = NULL;
579
580 switch( rAny.get<sal_Int16>() )
581 {
582 case awt::FontUnderline::NONE:
583 value = "none";
584 break;
585
586 case awt::FontUnderline::SINGLE:
587 value = "single";
588 break;
589
590 case awt::FontUnderline::DOUBLE:
591 value = "double";
592 break;
593
594 default:
595 break;
596 }
597
598 if( value )
599 return g_strdup( value );
600
601 return NULL;
602 }
603
604 static bool
String2Underline(uno::Any & rAny,const gchar * value)605 String2Underline( uno::Any& rAny, const gchar * value )
606 {
607 short nUnderline;
608
609 if( strncmp( value, STRNCMP_PARAM( "none" ) ) )
610 nUnderline = awt::FontUnderline::NONE;
611 else if( strncmp( value, STRNCMP_PARAM( "single" ) ) )
612 nUnderline = awt::FontUnderline::SINGLE;
613 else if( strncmp( value, STRNCMP_PARAM( "double" ) ) )
614 nUnderline = awt::FontUnderline::DOUBLE;
615 else
616 return false;
617
618 rAny = uno::makeAny( nUnderline );
619 return true;
620 }
621
622 /*****************************************************************************/
623
624 static gchar*
GetString(const uno::Any & rAny)625 GetString(const uno::Any& rAny)
626 {
627 rtl::OString aFontName = rtl::OUStringToOString( rAny.get< rtl::OUString > (), RTL_TEXTENCODING_UTF8 );
628
629 if( aFontName.getLength() )
630 return g_strdup( aFontName.getStr() );
631
632 return NULL;
633 }
634
635 static bool
SetString(uno::Any & rAny,const gchar * value)636 SetString( uno::Any& rAny, const gchar * value )
637 {
638 rtl::OString aFontName( value );
639
640 if( aFontName.getLength() )
641 {
642 rAny = uno::makeAny( rtl::OStringToOUString( aFontName, RTL_TEXTENCODING_UTF8 ) );
643 return true;
644 }
645
646 return false;
647 }
648
649 /*****************************************************************************/
650
651 // @see http://developer.gnome.org/doc/API/2.0/atk/AtkText.html#AtkTextAttribute
652
653 // CMM = 100th of mm
654 static gchar*
CMM2UnitString(const uno::Any & rAny)655 CMM2UnitString(const uno::Any& rAny)
656 {
657 double fValue = rAny.get<sal_Int32>();
658 fValue = fValue * 0.01;
659
660 return g_strdup_printf( "%gmm", fValue );
661 }
662
663 static bool
UnitString2CMM(uno::Any & rAny,const gchar * value)664 UnitString2CMM( uno::Any& rAny, const gchar * value )
665 {
666 float fValue = 0.0; // pb: dont use double here because of warning on linux
667
668 if( 1 != sscanf( value, "%gmm", &fValue ) )
669 return false;
670
671 fValue = fValue * 100;
672
673 rAny = uno::makeAny( (sal_Int32) fValue);
674 return true;
675 }
676
677 /*****************************************************************************/
678
679 static const gchar * bool_values[] = { "true", "false" };
680
681 static gchar *
Bool2String(const uno::Any & rAny)682 Bool2String( const uno::Any& rAny )
683 {
684 int n = 1;
685
686 if( rAny.get<sal_Bool>() )
687 n = 0;
688
689 return g_strdup( bool_values[n] );
690 }
691
692 static bool
String2Bool(uno::Any & rAny,const gchar * value)693 String2Bool( uno::Any& rAny, const gchar * value )
694 {
695 sal_Bool bValue;
696
697 if( strncmp( value, STRNCMP_PARAM( "true" ) ) )
698 bValue = sal_True;
699 else if( strncmp( value, STRNCMP_PARAM( "false" ) ) )
700 bValue = sal_False;
701 else
702 return false;
703
704 rAny = uno::makeAny(bValue);
705 return true;
706 }
707
708 /*****************************************************************************/
709
710 static gchar*
Scale2String(const uno::Any & rAny)711 Scale2String( const uno::Any& rAny )
712 {
713 return g_strdup_printf( "%g", (double) (rAny.get< sal_Int16 > ()) / 100 );
714 }
715
716 static bool
String2Scale(uno::Any & rAny,const gchar * value)717 String2Scale( uno::Any& rAny, const gchar * value )
718 {
719 double dval;
720
721 if( 1 != sscanf( value, "%lg", &dval ) )
722 return false;
723
724 rAny = uno::makeAny((sal_Int16) (dval * 100));
725 return true;
726 }
727
728 /*****************************************************************************/
729
730 static gchar *
CaseMap2String(const uno::Any & rAny)731 CaseMap2String( const uno::Any& rAny )
732 {
733 const gchar * value = NULL;
734
735 switch( rAny.get<short>() )
736 {
737 case style::CaseMap::SMALLCAPS:
738 value = "small_caps";
739 break;
740
741 default:
742 value = "normal";
743 break;
744 }
745
746 if( value )
747 return g_strdup( value );
748
749 return NULL;
750 }
751
752 static bool
String2CaseMap(uno::Any & rAny,const gchar * value)753 String2CaseMap( uno::Any& rAny, const gchar * value )
754 {
755 short nCaseMap;
756
757 if( strncmp( value, STRNCMP_PARAM( "normal" ) ) )
758 nCaseMap = style::CaseMap::NONE;
759 else if( strncmp( value, STRNCMP_PARAM( "small_caps" ) ) )
760 nCaseMap = style::CaseMap::SMALLCAPS;
761 else
762 return false;
763
764 rAny = uno::makeAny( nCaseMap );
765 return true;
766 }
767
768 /*****************************************************************************/
769
770 const gchar * font_stretch[] = {
771 "ultra_condensed",
772 "extra_condensed",
773 "condensed",
774 "semi_condensed",
775 "normal",
776 "semi_expanded",
777 "expanded",
778 "extra_expanded",
779 "ultra_expanded"
780 };
781
782 static gchar*
Kerning2Stretch(const uno::Any & rAny)783 Kerning2Stretch(const uno::Any& rAny)
784 {
785 sal_Int16 n = rAny.get<sal_Int16>();
786 int i = 4;
787
788 // No good idea for a mapping - just return the basic info
789 if( n < 0 )
790 i=2;
791 else if( n > 0 )
792 i=6;
793
794 return g_strdup(font_stretch[i]);
795 }
796
797 /*****************************************************************************/
798
799 static gchar*
Locale2String(const uno::Any & rAny)800 Locale2String(const uno::Any& rAny)
801 {
802 lang::Locale aLocale = rAny.get<lang::Locale> ();
803 return g_strdup_printf( "%s-%s",
804 rtl::OUStringToOString( aLocale.Language, RTL_TEXTENCODING_ASCII_US).getStr(),
805 rtl::OUStringToOString( aLocale.Country, RTL_TEXTENCODING_ASCII_US).toAsciiLowerCase().getStr() );
806 }
807
808 static bool
String2Locale(uno::Any & rAny,const gchar * value)809 String2Locale( uno::Any& rAny, const gchar * value )
810 {
811 bool ret = false;
812
813 gchar ** str_array = g_strsplit_set( value, "-.@", -1 );
814 if( str_array[0] != NULL )
815 {
816 ret = true;
817
818 lang::Locale aLocale;
819
820 aLocale.Language = rtl::OUString::createFromAscii(str_array[0]);
821 if( str_array[1] != NULL )
822 {
823 gchar * country = g_ascii_strup(str_array[1], -1);
824 aLocale.Country = rtl::OUString::createFromAscii(country);
825 g_free(country);
826 }
827
828 rAny = uno::makeAny(aLocale);
829 }
830
831 g_strfreev(str_array);
832 return ret;
833 }
834
835 /*****************************************************************************/
836
837 // @see http://www.w3.org/TR/2002/WD-css3-fonts-20020802/#font-effect-prop
838 static const gchar * relief[] = { "none", "emboss", "engrave" };
839 static const gchar * outline = "outline";
840
841 static gchar *
get_font_effect(const uno::Sequence<beans::PropertyValue> & rAttributeList,sal_Int32 nContourIndex,sal_Int32 nReliefIndex)842 get_font_effect(const uno::Sequence< beans::PropertyValue >& rAttributeList,
843 sal_Int32 nContourIndex, sal_Int32 nReliefIndex)
844 {
845 if( nContourIndex != -1 )
846 {
847 if( rAttributeList[nContourIndex].Value.get<sal_Bool>() )
848 return g_strdup(outline);
849 }
850
851 if( nReliefIndex != -1 )
852 {
853 sal_Int16 n = rAttributeList[nReliefIndex].Value.get<sal_Int16>();
854 if( n < 3)
855 return g_strdup(relief[n]);
856 }
857
858 return NULL;
859 }
860
861 /*****************************************************************************/
862
863 // @see http://www.w3.org/TR/REC-CSS2/text.html#lining-striking-props
864
865
866 enum
867 {
868 DECORATION_NONE = 0,
869 DECORATION_BLINK,
870 DECORATION_UNDERLINE,
871 DECORATION_LINE_THROUGH
872 };
873
874
875 static const gchar * decorations[] = { "none", "blink", "underline", "line-through" };
876
877 static gchar *
get_text_decoration(const uno::Sequence<beans::PropertyValue> & rAttributeList,sal_Int32 nBlinkIndex,sal_Int32 nUnderlineIndex,sal_Int16 nStrikeoutIndex)878 get_text_decoration(const uno::Sequence< beans::PropertyValue >& rAttributeList,
879 sal_Int32 nBlinkIndex, sal_Int32 nUnderlineIndex,
880 sal_Int16 nStrikeoutIndex)
881 {
882 gchar * value_list[4] = { NULL, NULL, NULL, NULL };
883 gint count = 0;
884
885 // no property value found
886 if( ( nBlinkIndex == -1 ) && (nUnderlineIndex == -1 ) && (nStrikeoutIndex == -1))
887 return NULL;
888
889 if( nBlinkIndex != -1 )
890 {
891 if( rAttributeList[nBlinkIndex].Value.get<sal_Bool>() )
892 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_BLINK]);
893 }
894 if( nUnderlineIndex != -1 )
895 {
896 sal_Int16 n = rAttributeList[nUnderlineIndex].Value.get<sal_Int16> ();
897 if( n != awt::FontUnderline::NONE )
898 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_UNDERLINE]);
899 }
900 if( nStrikeoutIndex != -1 )
901 {
902 sal_Int16 n = rAttributeList[nStrikeoutIndex].Value.get<sal_Int16> ();
903 if( n != awt::FontStrikeout::NONE && n != awt::FontStrikeout::DONTKNOW )
904 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_LINE_THROUGH]);
905 }
906
907 if( count == 0 )
908 value_list[count++] = const_cast <gchar *> (decorations[DECORATION_NONE]);
909
910 return g_strjoinv(" ", value_list);
911 }
912
913
914 /*****************************************************************************/
915
916 // @see http://www.w3.org/TR/REC-CSS2/text.html#propdef-text-shadow
917
918 static const gchar * shadow_values[] = { "none", "black" };
919
920 static gchar *
Bool2Shadow(const uno::Any & rAny)921 Bool2Shadow( const uno::Any& rAny )
922 {
923 int n = 0;
924
925 if( rAny.get<sal_Bool>() )
926 n = 1;
927
928 return g_strdup( shadow_values[n] );
929 }
930
931 /*****************************************************************************/
932
933 static gchar *
Short2Degree(const uno::Any & rAny)934 Short2Degree( const uno::Any& rAny )
935 {
936 float f = rAny.get<sal_Int16>() / 10;
937 return g_strdup_printf( "%g", f );
938 }
939
940 /*****************************************************************************/
941
942 const gchar * directions[] = { "ltr", "rtl", "rtl", "ltr", "none" };
943
944 static gchar *
WritingMode2Direction(const uno::Any & rAny)945 WritingMode2Direction( const uno::Any& rAny )
946 {
947 sal_Int16 n = rAny.get<sal_Int16>();
948
949 if( 0 <= n && n <= text::WritingMode2::PAGE )
950 return g_strdup(directions[n]);
951
952 return NULL;
953 }
954
955 // @see http://www.w3.org/TR/2001/WD-css3-text-20010517/#PrimaryTextAdvanceDirection
956
957 const gchar * writing_modes[] = { "lr-tb", "rl-tb", "tb-rl", "tb-lr", "none" };
958 static gchar *
WritingMode2String(const uno::Any & rAny)959 WritingMode2String( const uno::Any& rAny )
960 {
961 sal_Int16 n = rAny.get<sal_Int16>();
962
963 if( 0 <= n && n <= text::WritingMode2::PAGE )
964 return g_strdup(writing_modes[n]);
965
966 return NULL;
967 }
968
969 /*****************************************************************************/
970
971 const char * baseline_values[] = { "baseline", "sub", "super" };
972
973 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-vertical-align
974 static gchar *
Escapement2VerticalAlign(const uno::Any & rAny)975 Escapement2VerticalAlign( const uno::Any& rAny )
976 {
977 sal_Int16 n = rAny.get<sal_Int16>();
978 gchar * ret = NULL;
979
980 // Values are in %, 101% means "automatic"
981 if( n == 0 )
982 ret = g_strdup(baseline_values[0]);
983 else if( n == 101 )
984 ret = g_strdup(baseline_values[2]);
985 else if( n == -101 )
986 ret = g_strdup(baseline_values[1]);
987 else
988 ret = g_strdup_printf( "%d%%", n );
989
990 return ret;
991 }
992
993 /*****************************************************************************/
994
995 // @see http://www.w3.org/TR/REC-CSS2/visudet.html#propdef-line-height
996 static gchar *
LineSpacing2LineHeight(const uno::Any & rAny)997 LineSpacing2LineHeight( const uno::Any& rAny )
998 {
999 style::LineSpacing ls;
1000 gchar * ret = NULL;
1001
1002 if( rAny >>= ls )
1003 {
1004 if( ls.Mode == style::LineSpacingMode::PROP )
1005 ret = g_strdup_printf( "%d%%", ls.Height );
1006 else if( ls.Mode == style::LineSpacingMode::FIX )
1007 ret = g_strdup_printf( "%.3gpt", toPoint(ls.Height) );
1008 }
1009
1010 return ret;
1011 }
1012
1013 /*****************************************************************************/
1014
1015 // @see http://www.w3.org/People/howcome/t/970224HTMLERB-CSS/WD-tabs-970117.html
1016 static gchar *
TabStopList2String(const uno::Any & rAny,bool default_tabs)1017 TabStopList2String( const uno::Any& rAny, bool default_tabs )
1018 {
1019 uno::Sequence< style::TabStop > theTabStops;
1020 gchar * ret = NULL;
1021
1022 if( rAny >>= theTabStops)
1023 {
1024 sal_Int32 indexOfTab = 0;
1025 sal_Int32 numberOfTabs = theTabStops.getLength();
1026 sal_Unicode lastFillChar = (sal_Unicode) ' ';
1027
1028 for( ; indexOfTab < numberOfTabs; ++indexOfTab )
1029 {
1030 bool is_default_tab = (style::TabAlign_DEFAULT == theTabStops[indexOfTab].Alignment);
1031
1032 if( is_default_tab != default_tabs )
1033 continue;
1034
1035 double fValue = theTabStops[indexOfTab].Position;
1036 fValue = fValue * 0.01;
1037
1038 const gchar * tab_align = "";
1039 switch( theTabStops[indexOfTab].Alignment )
1040 {
1041 case style::TabAlign_LEFT :
1042 tab_align = "left ";
1043 break;
1044 case style::TabAlign_CENTER :
1045 tab_align = "center ";
1046 break;
1047 case style::TabAlign_RIGHT :
1048 tab_align = "right ";
1049 break;
1050 case style::TabAlign_DECIMAL :
1051 tab_align = "decimal ";
1052 break;
1053 default:
1054 break;
1055 }
1056
1057 const gchar * lead_char = "";
1058
1059 if( theTabStops[indexOfTab].FillChar != lastFillChar )
1060 {
1061 lastFillChar = theTabStops[indexOfTab].FillChar;
1062 switch (lastFillChar)
1063 {
1064 case (sal_Unicode) ' ':
1065 lead_char = "blank ";
1066 break;
1067
1068 case (sal_Unicode) '.':
1069 lead_char = "dotted ";
1070 break;
1071
1072 case (sal_Unicode) '-':
1073 lead_char = "dashed ";
1074 break;
1075
1076 case (sal_Unicode) '_':
1077 lead_char = "lined ";
1078 break;
1079
1080 default:
1081 lead_char = "custom ";
1082 break;
1083 }
1084 }
1085
1086 gchar * tab_str = g_strdup_printf( "%s%s%gmm", lead_char, tab_align, fValue );
1087
1088 if( ret )
1089 {
1090 gchar * old_tab_str = ret;
1091 ret = g_strconcat(old_tab_str, " ", tab_str, NULL /* terminated */);
1092 g_free( old_tab_str );
1093 }
1094 else
1095 ret = tab_str;
1096 }
1097 }
1098
1099 return ret;
1100 }
1101
1102 static gchar *
TabStops2String(const uno::Any & rAny)1103 TabStops2String( const uno::Any& rAny )
1104 {
1105 return TabStopList2String(rAny, false);
1106 }
1107
1108 static gchar *
DefaultTabStops2String(const uno::Any & rAny)1109 DefaultTabStops2String( const uno::Any& rAny )
1110 {
1111 return TabStopList2String(rAny, true);
1112 }
1113
1114 /*****************************************************************************/
1115
1116 extern "C" int
attr_compare(const void * p1,const void * p2)1117 attr_compare(const void *p1,const void *p2)
1118 {
1119 const rtl_uString * pustr = (const rtl_uString *) p1;
1120 const char * pc = *((const char **) p2);
1121
1122 return rtl_ustr_ascii_compare_WithLength(pustr->buffer, pustr->length, pc);
1123 }
1124
1125 static void
find_exported_attributes(sal_Int32 * pArray,const com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue> & rAttributeList)1126 find_exported_attributes( sal_Int32 *pArray,
1127 const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& rAttributeList )
1128 {
1129 for( sal_Int32 i = 0; i < rAttributeList.getLength(); i++ )
1130 {
1131 const char ** pAttr = (const char **) bsearch(rAttributeList[i].Name.pData,
1132 ExportedTextAttributes, TEXT_ATTRIBUTE_LAST, sizeof(const char *),
1133 attr_compare);
1134
1135 if( pAttr )
1136 {
1137 sal_Int32 nIndex = pAttr - ExportedTextAttributes;
1138 pArray[nIndex] = i;
1139 }
1140 }
1141 }
1142
1143 /*****************************************************************************/
1144
1145 static AtkAttributeSet*
attribute_set_prepend(AtkAttributeSet * attribute_set,AtkTextAttribute attribute,gchar * value)1146 attribute_set_prepend( AtkAttributeSet* attribute_set,
1147 AtkTextAttribute attribute,
1148 gchar * value )
1149 {
1150 if( value )
1151 {
1152 AtkAttribute *at = (AtkAttribute *) g_malloc( sizeof (AtkAttribute) );
1153 at->name = g_strdup( atk_text_attribute_get_name( attribute ) );
1154 at->value = value;
1155
1156 return g_slist_prepend(attribute_set, at);
1157 }
1158
1159 return attribute_set;
1160 }
1161
1162 /*****************************************************************************/
1163
1164 AtkAttributeSet*
attribute_set_new_from_property_values(const uno::Sequence<beans::PropertyValue> & rAttributeList,bool run_attributes_only,AtkText * text)1165 attribute_set_new_from_property_values(
1166 const uno::Sequence< beans::PropertyValue >& rAttributeList,
1167 bool run_attributes_only,
1168 AtkText *text)
1169 {
1170 AtkAttributeSet* attribute_set = NULL;
1171
1172 sal_Int32 aIndexList[TEXT_ATTRIBUTE_LAST] = { -1 };
1173
1174 // Initialize index array with -1
1175 for( sal_Int32 attr = 0; attr < TEXT_ATTRIBUTE_LAST; ++attr )
1176 aIndexList[attr] = -1;
1177
1178 find_exported_attributes(aIndexList, rAttributeList);
1179
1180 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_BG_COLOR,
1181 get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_BACKGROUND_COLOR, run_attributes_only ? NULL : text ) );
1182
1183 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FG_COLOR,
1184 get_color_value(rAttributeList, aIndexList, TEXT_ATTRIBUTE_FOREGROUND_COLOR, run_attributes_only ? NULL : text) );
1185
1186 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INVISIBLE,
1187 get_bool_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HIDDEN]));
1188
1189 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_UNDERLINE,
1190 get_underline_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_UNDERLINE]));
1191
1192 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRIKETHROUGH,
1193 get_strikethrough_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1194
1195 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SIZE,
1196 get_height_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_HEIGHT]));
1197
1198 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_WEIGHT,
1199 get_weight_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WEIGHT]));
1200
1201 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_FAMILY_NAME,
1202 get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FONT_NAME]));
1203
1204 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_VARIANT,
1205 get_variant_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CASEMAP]));
1206
1207 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STYLE,
1208 get_style_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_POSTURE]));
1209
1210 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_SCALE,
1211 get_scale_width(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SCALE]));
1212
1213 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LANGUAGE,
1214 get_language_string(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LOCALE]));
1215
1216 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_DIRECTION,
1217 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2Direction));
1218
1219 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_STRETCH,
1220 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_KERNING], Kerning2Stretch));
1221
1222 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_font_effect )
1223 atk_text_attribute_font_effect = atk_text_attribute_register("font-effect");
1224
1225 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_font_effect,
1226 get_font_effect(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CONTOURED], aIndexList[TEXT_ATTRIBUTE_RELIEF]));
1227
1228 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_decoration )
1229 atk_text_attribute_decoration = atk_text_attribute_register("text-decoration");
1230
1231 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_decoration,
1232 get_text_decoration(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BLINKING],
1233 aIndexList[TEXT_ATTRIBUTE_UNDERLINE], aIndexList[TEXT_ATTRIBUTE_STRIKETHROUGH]));
1234
1235 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_rotation )
1236 atk_text_attribute_rotation = atk_text_attribute_register("text-rotation");
1237
1238 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_rotation,
1239 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_ROTATION], Short2Degree));
1240
1241 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_shadow )
1242 atk_text_attribute_shadow = atk_text_attribute_register("text-shadow");
1243
1244 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_shadow,
1245 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_SHADOWED], Bool2Shadow));
1246
1247 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_writing_mode )
1248 atk_text_attribute_writing_mode = atk_text_attribute_register("writing-mode");
1249
1250 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_writing_mode,
1251 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_WRITING_MODE], WritingMode2String));
1252
1253 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_vertical_align )
1254 atk_text_attribute_vertical_align = atk_text_attribute_register("vertical-align");
1255
1256 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_vertical_align,
1257 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_CHAR_ESCAPEMENT], Escapement2VerticalAlign));
1258
1259 if( run_attributes_only )
1260 return attribute_set;
1261
1262 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_LEFT_MARGIN,
1263 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LEFT_MARGIN]));
1264
1265 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_RIGHT_MARGIN,
1266 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_RIGHT_MARGIN]));
1267
1268 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_INDENT,
1269 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_FIRST_LINE_INDENT]));
1270
1271 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES,
1272 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TOP_MARGIN]));
1273
1274 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES,
1275 get_cmm_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_BOTTOM_MARGIN]));
1276
1277 attribute_set = attribute_set_prepend(attribute_set, ATK_TEXT_ATTR_JUSTIFICATION,
1278 get_justification_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_JUSTIFICATION]));
1279
1280 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_paragraph_style )
1281 atk_text_attribute_paragraph_style = atk_text_attribute_register("paragraph-style");
1282
1283 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_paragraph_style,
1284 get_string_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_STYLE_NAME]));
1285
1286 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_line_height )
1287 atk_text_attribute_line_height = atk_text_attribute_register("line-height");
1288
1289 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_line_height,
1290 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_LINE_SPACING], LineSpacing2LineHeight));
1291
1292 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_interval )
1293 atk_text_attribute_tab_interval = atk_text_attribute_register("tab-interval");
1294
1295 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_interval,
1296 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], DefaultTabStops2String));
1297
1298 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tab_stops )
1299 atk_text_attribute_tab_stops = atk_text_attribute_register("tab-stops");
1300
1301 attribute_set = attribute_set_prepend(attribute_set, atk_text_attribute_tab_stops,
1302 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_TAB_STOPS], TabStops2String));
1303
1304 // --> OD 2010-03-05 #i92233#
1305 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_mm_to_pixel_ratio )
1306 atk_text_attribute_mm_to_pixel_ratio = atk_text_attribute_register("mm-to-pixel-ratio");
1307
1308 attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_mm_to_pixel_ratio,
1309 get_value(rAttributeList, aIndexList[TEXT_ATTRIBUTE_MM_TO_PIXEL_RATIO], Float2String));
1310 // <--
1311
1312 return attribute_set;
1313 }
1314
1315
attribute_set_prepend_misspelled(AtkAttributeSet * attribute_set)1316 AtkAttributeSet* attribute_set_prepend_misspelled( AtkAttributeSet* attribute_set )
1317 {
1318 if( ATK_TEXT_ATTR_INVALID == atk_text_attribute_misspelled )
1319 atk_text_attribute_misspelled = atk_text_attribute_register( "text-spelling" );
1320
1321 attribute_set = attribute_set_prepend( attribute_set, atk_text_attribute_misspelled,
1322 g_strdup_printf( "misspelled" ) );
1323
1324 return attribute_set;
1325 }
1326
1327 // --> OD 2010-03-01 #i92232#
attribute_set_prepend_tracked_change_insertion(AtkAttributeSet * attribute_set)1328 AtkAttributeSet* attribute_set_prepend_tracked_change_insertion( AtkAttributeSet* attribute_set )
1329 {
1330 if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1331 {
1332 atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1333 }
1334
1335 attribute_set = attribute_set_prepend( attribute_set,
1336 atk_text_attribute_tracked_change,
1337 g_strdup_printf( "insertion" ) );
1338
1339 return attribute_set;
1340 }
1341
attribute_set_prepend_tracked_change_deletion(AtkAttributeSet * attribute_set)1342 AtkAttributeSet* attribute_set_prepend_tracked_change_deletion( AtkAttributeSet* attribute_set )
1343 {
1344 if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1345 {
1346 atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1347 }
1348
1349 attribute_set = attribute_set_prepend( attribute_set,
1350 atk_text_attribute_tracked_change,
1351 g_strdup_printf( "deletion" ) );
1352
1353 return attribute_set;
1354 }
1355
attribute_set_prepend_tracked_change_formatchange(AtkAttributeSet * attribute_set)1356 AtkAttributeSet* attribute_set_prepend_tracked_change_formatchange( AtkAttributeSet* attribute_set )
1357 {
1358 if ( ATK_TEXT_ATTR_INVALID == atk_text_attribute_tracked_change )
1359 {
1360 atk_text_attribute_tracked_change = atk_text_attribute_register( "text-tracked-change" );
1361 }
1362
1363 attribute_set = attribute_set_prepend( attribute_set,
1364 atk_text_attribute_tracked_change,
1365 g_strdup_printf( "attribute-change" ) );
1366
1367 return attribute_set;
1368 }
1369 // <--
1370
1371 /*****************************************************************************/
1372
1373 struct AtkTextAttrMapping
1374 {
1375 const char * name;
1376 TextPropertyValueFunc toPropertyValue;
1377 };
1378
1379 const AtkTextAttrMapping g_TextAttrMap[] =
1380 {
1381 { "", InvalidValue }, // ATK_TEXT_ATTR_INVALID = 0
1382 { "ParaLeftMargin", UnitString2CMM }, // ATK_TEXT_ATTR_LEFT_MARGIN
1383 { "ParaRightMargin", UnitString2CMM }, // ATK_TEXT_ATTR_RIGHT_MARGIN
1384 { "ParaFirstLineIndent", UnitString2CMM }, // ATK_TEXT_ATTR_INDENT
1385 { "CharHidden", String2Bool }, // ATK_TEXT_ATTR_INVISIBLE
1386 { "", InvalidValue }, // ATK_TEXT_ATTR_EDITABLE
1387 { "ParaTopMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_ABOVE_LINES
1388 { "ParaBottomMargin", UnitString2CMM }, // ATK_TEXT_ATTR_PIXELS_BELOW_LINES
1389 { "", InvalidValue }, // ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP
1390 { "", InvalidValue }, // ATK_TEXT_ATTR_BG_FULL_HEIGHT
1391 { "", InvalidValue }, // ATK_TEXT_ATTR_RISE
1392 { "CharUnderline", String2Underline }, // ATK_TEXT_ATTR_UNDERLINE
1393 { "CharStrikeout", String2Strikeout }, // ATK_TEXT_ATTR_STRIKETHROUGH
1394 { "CharHeight", String2Float }, // ATK_TEXT_ATTR_SIZE
1395 { "CharScaleWidth", String2Scale }, // ATK_TEXT_ATTR_SCALE
1396 { "CharWeight", String2Weight }, // ATK_TEXT_ATTR_WEIGHT
1397 { "CharLocale", String2Locale }, // ATK_TEXT_ATTR_LANGUAGE
1398 { "CharFontName", SetString }, // ATK_TEXT_ATTR_FAMILY_NAME
1399 { "CharBackColor", String2Color }, // ATK_TEXT_ATTR_BG_COLOR
1400 { "CharColor", String2Color }, // ATK_TEXT_ATTR_FG_COLOR
1401 { "", InvalidValue }, // ATK_TEXT_ATTR_BG_STIPPLE
1402 { "", InvalidValue }, // ATK_TEXT_ATTR_FG_STIPPLE
1403 { "", InvalidValue }, // ATK_TEXT_ATTR_WRAP_MODE
1404 { "", InvalidValue }, // ATK_TEXT_ATTR_DIRECTION
1405 { "ParaAdjust", Justification2Adjust }, // ATK_TEXT_ATTR_JUSTIFICATION
1406 { "", InvalidValue }, // ATK_TEXT_ATTR_STRETCH
1407 { "CharCaseMap", String2CaseMap }, // ATK_TEXT_ATTR_VARIANT
1408 { "CharPosture", Style2FontSlant } // ATK_TEXT_ATTR_STYLE
1409 };
1410
1411 static const sal_Int32 g_TextAttrMapSize = sizeof( g_TextAttrMap ) / sizeof( AtkTextAttrMapping );
1412
1413 /*****************************************************************************/
1414
1415 bool
attribute_set_map_to_property_values(AtkAttributeSet * attribute_set,uno::Sequence<beans::PropertyValue> & rValueList)1416 attribute_set_map_to_property_values(
1417 AtkAttributeSet* attribute_set,
1418 uno::Sequence< beans::PropertyValue >& rValueList )
1419 {
1420 // Ensure enough space ..
1421 uno::Sequence< beans::PropertyValue > aAttributeList (g_TextAttrMapSize);
1422
1423 sal_Int32 nIndex = 0;
1424 for( GSList * item = attribute_set; item != NULL; item = g_slist_next( item ) )
1425 {
1426 AtkAttribute* attribute = (AtkAttribute *) item;
1427
1428 AtkTextAttribute text_attr = atk_text_attribute_for_name( attribute->name );
1429 if( text_attr < g_TextAttrMapSize )
1430 {
1431 if( g_TextAttrMap[text_attr].name[0] != '\0' )
1432 {
1433 if( ! g_TextAttrMap[text_attr].toPropertyValue( aAttributeList[nIndex].Value, attribute->value) )
1434 return false;
1435
1436 aAttributeList[nIndex].Name = rtl::OUString::createFromAscii( g_TextAttrMap[text_attr].name );
1437 aAttributeList[nIndex].State = beans::PropertyState_DIRECT_VALUE;
1438 ++nIndex;
1439 }
1440 }
1441 else
1442 {
1443 // Unsupported text attribute
1444 return false;
1445 }
1446 }
1447
1448 aAttributeList.realloc( nIndex );
1449 rValueList = aAttributeList;
1450 return true;
1451 }
1452
1453