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