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