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