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