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_xmloff.hxx" 30 31 32 #include <bordrhdl.hxx> 33 #include <xmloff/xmltoken.hxx> 34 #include <xmloff/xmluconv.hxx> 35 #include <rtl/ustrbuf.hxx> 36 #include <com/sun/star/uno/Any.hxx> 37 #include <com/sun/star/table/BorderLine.hpp> 38 39 using ::rtl::OUString; 40 using ::rtl::OUStringBuffer; 41 42 using namespace ::com::sun::star; 43 using namespace ::xmloff::token; 44 45 // copied from svx/boxitem.hxx 46 #define DEF_LINE_WIDTH_0 1 47 #define DEF_LINE_WIDTH_1 35 48 #define DEF_LINE_WIDTH_2 88 49 #define DEF_LINE_WIDTH_3 141 50 #define DEF_LINE_WIDTH_4 176 51 52 #define DEF_MAX_LINE_WIDHT DEF_LINE_WIDTH_4 53 #define DEF_MAX_LINE_DIST DEF_LINE_WIDTH_2 54 55 #define DEF_DOUBLE_LINE0_OUT DEF_LINE_WIDTH_0 56 #define DEF_DOUBLE_LINE0_IN DEF_LINE_WIDTH_0 57 #define DEF_DOUBLE_LINE0_DIST DEF_LINE_WIDTH_1 58 59 #define DEF_DOUBLE_LINE1_OUT DEF_LINE_WIDTH_1 60 #define DEF_DOUBLE_LINE1_IN DEF_LINE_WIDTH_1 61 #define DEF_DOUBLE_LINE1_DIST DEF_LINE_WIDTH_1 62 63 #define DEF_DOUBLE_LINE2_OUT DEF_LINE_WIDTH_2 64 #define DEF_DOUBLE_LINE2_IN DEF_LINE_WIDTH_2 65 #define DEF_DOUBLE_LINE2_DIST DEF_LINE_WIDTH_2 66 67 #define DEF_DOUBLE_LINE3_OUT DEF_LINE_WIDTH_2 68 #define DEF_DOUBLE_LINE3_IN DEF_LINE_WIDTH_1 69 #define DEF_DOUBLE_LINE3_DIST DEF_LINE_WIDTH_2 70 71 #define DEF_DOUBLE_LINE4_OUT DEF_LINE_WIDTH_1 72 #define DEF_DOUBLE_LINE4_IN DEF_LINE_WIDTH_2 73 #define DEF_DOUBLE_LINE4_DIST DEF_LINE_WIDTH_1 74 75 #define DEF_DOUBLE_LINE5_OUT DEF_LINE_WIDTH_3 76 #define DEF_DOUBLE_LINE5_IN DEF_LINE_WIDTH_2 77 #define DEF_DOUBLE_LINE5_DIST DEF_LINE_WIDTH_2 78 79 #define DEF_DOUBLE_LINE6_OUT DEF_LINE_WIDTH_2 80 #define DEF_DOUBLE_LINE6_IN DEF_LINE_WIDTH_3 81 #define DEF_DOUBLE_LINE6_DIST DEF_LINE_WIDTH_2 82 83 #define DEF_DOUBLE_LINE7_OUT DEF_LINE_WIDTH_0 84 #define DEF_DOUBLE_LINE7_IN DEF_LINE_WIDTH_0 85 #define DEF_DOUBLE_LINE7_DIST DEF_LINE_WIDTH_2 86 87 #define DEF_DOUBLE_LINE8_OUT DEF_LINE_WIDTH_1 88 #define DEF_DOUBLE_LINE8_IN DEF_LINE_WIDTH_0 89 #define DEF_DOUBLE_LINE8_DIST DEF_LINE_WIDTH_2 90 91 #define DEF_DOUBLE_LINE9_OUT DEF_LINE_WIDTH_2 92 #define DEF_DOUBLE_LINE9_IN DEF_LINE_WIDTH_0 93 #define DEF_DOUBLE_LINE9_DIST DEF_LINE_WIDTH_2 94 95 #define DEF_DOUBLE_LINE10_OUT DEF_LINE_WIDTH_3 96 #define DEF_DOUBLE_LINE10_IN DEF_LINE_WIDTH_0 97 #define DEF_DOUBLE_LINE10_DIST DEF_LINE_WIDTH_2 98 99 // finished copy 100 101 #define SVX_XML_BORDER_STYLE_NONE 0 102 #define SVX_XML_BORDER_STYLE_SOLID 1 103 #define SVX_XML_BORDER_STYLE_DOUBLE 2 104 105 #define SVX_XML_BORDER_WIDTH_THIN 0 106 #define SVX_XML_BORDER_WIDTH_MIDDLE 1 107 #define SVX_XML_BORDER_WIDTH_THICK 2 108 109 SvXMLEnumMapEntry pXML_BorderStyles[] = 110 { 111 { XML_NONE, SVX_XML_BORDER_STYLE_NONE }, 112 { XML_HIDDEN, SVX_XML_BORDER_STYLE_NONE }, 113 { XML_SOLID, SVX_XML_BORDER_STYLE_SOLID }, 114 { XML_DOUBLE, SVX_XML_BORDER_STYLE_DOUBLE }, 115 { XML_DOTTED, SVX_XML_BORDER_STYLE_SOLID }, 116 { XML_DASHED, SVX_XML_BORDER_STYLE_SOLID }, 117 { XML_GROOVE, SVX_XML_BORDER_STYLE_SOLID }, 118 { XML_RIDGE, SVX_XML_BORDER_STYLE_SOLID }, 119 { XML_INSET, SVX_XML_BORDER_STYLE_SOLID }, 120 { XML_OUTSET, SVX_XML_BORDER_STYLE_SOLID }, 121 { XML_TOKEN_INVALID, 0 } 122 }; 123 124 SvXMLEnumMapEntry pXML_NamedBorderWidths[] = 125 { 126 { XML_THIN, SVX_XML_BORDER_WIDTH_THIN }, 127 { XML_MIDDLE, SVX_XML_BORDER_WIDTH_MIDDLE }, 128 { XML_THICK, SVX_XML_BORDER_WIDTH_THICK }, 129 { XML_TOKEN_INVALID, 0 } 130 }; 131 // mapping tables to map external xml input to intarnal box line widths 132 133 // Ein Eintrag besteht aus vier USHORTs. Der erste ist die Gesamtbreite, 134 // die anderen sind die 3 Einzelbreiten 135 136 #define SBORDER_ENTRY( n ) \ 137 DEF_LINE_WIDTH_##n, DEF_LINE_WIDTH_##n, 0, 0 138 139 #define DBORDER_ENTRY( n ) \ 140 DEF_DOUBLE_LINE##n##_OUT + DEF_DOUBLE_LINE##n##_IN + \ 141 DEF_DOUBLE_LINE##n##_DIST, \ 142 DEF_DOUBLE_LINE##n##_OUT, \ 143 DEF_DOUBLE_LINE##n##_IN, \ 144 DEF_DOUBLE_LINE##n##_DIST 145 146 #define TDBORDER_ENTRY( n ) \ 147 DEF_DOUBLE_LINE##n##_OUT, \ 148 DEF_DOUBLE_LINE##n##_OUT, \ 149 DEF_DOUBLE_LINE##n##_IN, \ 150 DEF_DOUBLE_LINE##n##_DIST 151 152 153 static sal_uInt16 __READONLY_DATA aSBorderWidths[] = 154 { 155 SBORDER_ENTRY( 0 ), SBORDER_ENTRY( 1 ), SBORDER_ENTRY( 2 ), 156 SBORDER_ENTRY( 3 ), SBORDER_ENTRY( 4 ) 157 }; 158 159 static sal_uInt16 __READONLY_DATA aDBorderWidths[] = 160 { 161 DBORDER_ENTRY( 0 ), 162 DBORDER_ENTRY( 7 ), 163 DBORDER_ENTRY( 1 ), 164 DBORDER_ENTRY( 8 ), 165 DBORDER_ENTRY( 4 ), 166 DBORDER_ENTRY( 9 ), 167 DBORDER_ENTRY( 3 ), 168 DBORDER_ENTRY( 10 ), 169 DBORDER_ENTRY( 2 ), 170 DBORDER_ENTRY( 6 ), 171 DBORDER_ENTRY( 5 ) 172 }; 173 174 void lcl_frmitems_setXMLBorderWidth( table::BorderLine &rBorderLine, 175 sal_uInt16 nWidth, sal_Bool bDouble ) 176 { 177 #ifdef XML_CHECK_UI_CONTSTRAINS 178 const sal_uInt16 *aWidths; 179 sal_uInt16 nSize; 180 if( !bDouble ) 181 { 182 aWidths = aSBorderWidths; 183 nSize = sizeof( aSBorderWidths ); 184 } 185 else 186 { 187 aWidths = aDBorderWidths; 188 nSize = sizeof( aDBorderWidths ); 189 } 190 191 sal_uInt16 i = (nSize / sizeof(sal_uInt16)) - 4; 192 while( i>0 && 193 nWidth <= ((aWidths[i] + aWidths[i-4]) / 2) ) 194 { 195 i -= 4; 196 } 197 198 rBorderLine.OuterLineWidth = aWidths[i+1]; 199 rBorderLine.InnerLineWidth = aWidths[i+2]; 200 rBorderLine.LineDistance = aWidths[i+3]; 201 #else 202 if( bDouble ) 203 { 204 const sal_uInt16 *aWidths = aDBorderWidths; 205 sal_uInt16 nSize = sizeof( aDBorderWidths ); 206 sal_uInt16 i = (nSize / sizeof(sal_uInt16)) - 4; 207 while( i>0 && 208 nWidth <= ((aWidths[i] + aWidths[i-4]) / 2) ) 209 { 210 i -= 4; 211 } 212 213 rBorderLine.OuterLineWidth = aWidths[i+1]; 214 rBorderLine.InnerLineWidth = aWidths[i+2]; 215 rBorderLine.LineDistance = aWidths[i+3]; 216 } 217 else 218 { 219 rBorderLine.OuterLineWidth = 0 == nWidth ? DEF_LINE_WIDTH_0 : nWidth; 220 rBorderLine.InnerLineWidth = 0; 221 rBorderLine.LineDistance = 0; 222 223 } 224 #endif 225 } 226 227 228 /////////////////////////////////////////////////////////////////////////////// 229 // 230 // class XMLEscapementPropHdl 231 // 232 233 XMLBorderWidthHdl::~XMLBorderWidthHdl() 234 { 235 // nothing to do 236 } 237 238 sal_Bool XMLBorderWidthHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const 239 { 240 SvXMLTokenEnumerator aTokenEnum( rStrImpValue ); 241 242 sal_Int32 nInWidth, nDistance, nOutWidth; 243 244 OUString aToken; 245 if( !aTokenEnum.getNextToken( aToken ) ) 246 return sal_False; 247 248 if( !rUnitConverter.convertMeasure( nInWidth, aToken, 0, 500 ) ) 249 return sal_False; 250 251 if( !aTokenEnum.getNextToken( aToken ) ) 252 return sal_False; 253 254 if( !rUnitConverter.convertMeasure( nDistance, aToken, 0, 500 ) ) 255 return sal_False; 256 257 if( !aTokenEnum.getNextToken( aToken ) ) 258 return sal_False; 259 260 if( !rUnitConverter.convertMeasure( nOutWidth, aToken, 0, 500 ) ) 261 return sal_False; 262 263 #ifdef XML_CHECK_UI_CONSTRAINS 264 sal_uInt16 nSize = sizeof( aDBorderWidths ); 265 for( sal_uInt16 i=0; i < nSize; i += 4 ) 266 { 267 if( aDBorderWidths[i+1] == nOutWidth && 268 aDBorderWidths[i+2] == nInWidth && 269 aDBorderWidths[i+3] == nDistance ) 270 break; 271 } 272 273 sal_uInt16 nWidth = i < nSize ? 0 : nOutWidth + nInWidth + nDistance; 274 #endif 275 276 table::BorderLine aBorderLine; 277 if(!(rValue >>= aBorderLine)) 278 aBorderLine.Color = 0; 279 280 aBorderLine.InnerLineWidth = sal::static_int_cast< sal_Int16 >(nInWidth); 281 aBorderLine.OuterLineWidth = sal::static_int_cast< sal_Int16 >(nOutWidth); 282 aBorderLine.LineDistance = sal::static_int_cast< sal_Int16 >(nDistance); 283 284 rValue <<= aBorderLine; 285 return sal_True; 286 } 287 288 sal_Bool XMLBorderWidthHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const 289 { 290 OUStringBuffer aOut; 291 292 table::BorderLine aBorderLine; 293 if(!(rValue >>= aBorderLine)) 294 return sal_False; 295 296 if( aBorderLine.LineDistance == 0 && aBorderLine.InnerLineWidth == 0) 297 return sal_False; 298 299 rUnitConverter.convertMeasure( aOut, aBorderLine.InnerLineWidth ); 300 aOut.append( sal_Unicode( ' ' ) ); 301 rUnitConverter.convertMeasure( aOut, aBorderLine.LineDistance ); 302 aOut.append( sal_Unicode( ' ' ) ); 303 rUnitConverter.convertMeasure( aOut, aBorderLine.OuterLineWidth ); 304 305 rStrExpValue = aOut.makeStringAndClear(); 306 return sal_True; 307 } 308 309 /////////////////////////////////////////////////////////////////////////////// 310 // 311 // class XMLEscapementHeightPropHdl 312 // 313 314 XMLBorderHdl::~XMLBorderHdl() 315 { 316 // nothing to do 317 } 318 319 sal_Bool XMLBorderHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const 320 { 321 OUString aToken; 322 SvXMLTokenEnumerator aTokens( rStrImpValue ); 323 324 sal_Bool bHasStyle = sal_False; 325 sal_Bool bHasWidth = sal_False; 326 sal_Bool bHasColor = sal_False; 327 328 sal_uInt16 nStyle = USHRT_MAX; 329 sal_uInt16 nWidth = 0; 330 sal_uInt16 nNamedWidth = USHRT_MAX; 331 Color aColor; 332 333 sal_Int32 nTemp; 334 while( aTokens.getNextToken( aToken ) && aToken.getLength() != 0 ) 335 { 336 if( !bHasWidth && 337 rUnitConverter.convertEnum( nNamedWidth, aToken, 338 pXML_NamedBorderWidths ) ) 339 { 340 bHasWidth = sal_True; 341 } 342 else if( !bHasStyle && 343 rUnitConverter.convertEnum( nStyle, aToken, 344 pXML_BorderStyles ) ) 345 { 346 bHasStyle = sal_True; 347 } 348 else if( !bHasColor && rUnitConverter.convertColor( aColor, aToken ) ) 349 { 350 bHasColor = sal_True; 351 } 352 else if( !bHasWidth && 353 rUnitConverter.convertMeasure( nTemp, aToken, 0, 354 USHRT_MAX ) ) 355 { 356 nWidth = (sal_uInt16)nTemp; 357 bHasWidth = sal_True; 358 } 359 else 360 { 361 // missformed 362 return sal_False; 363 } 364 } 365 366 // if there is no style or a different style than none but no width, 367 // then the declaration is not valid. 368 if( !bHasStyle || (SVX_XML_BORDER_STYLE_NONE != nStyle && !bHasWidth) ) 369 return sal_False; 370 371 table::BorderLine aBorderLine; 372 if(!(rValue >>= aBorderLine)) 373 { 374 aBorderLine.Color = 0; 375 aBorderLine.InnerLineWidth = 0; 376 aBorderLine.OuterLineWidth = 0; 377 aBorderLine.LineDistance = 0; 378 } 379 380 // first of all, delete an empty line 381 sal_Bool bDouble = SVX_XML_BORDER_STYLE_DOUBLE == nStyle; 382 if( (bHasStyle && SVX_XML_BORDER_STYLE_NONE == nStyle) || 383 (bHasWidth && USHRT_MAX == nNamedWidth && 0 == nWidth) ) 384 { 385 aBorderLine.InnerLineWidth = 0; 386 aBorderLine.OuterLineWidth = 0; 387 aBorderLine.LineDistance = 0; 388 } 389 else if( bHasWidth ) 390 { 391 if( USHRT_MAX != nNamedWidth ) 392 { 393 const sal_uInt16 *aWidths = bDouble ? aDBorderWidths 394 : aSBorderWidths; 395 sal_uInt16 nNWidth = nNamedWidth * 4; 396 aBorderLine.OuterLineWidth = aWidths[nNWidth+1]; 397 aBorderLine.InnerLineWidth = aWidths[nNWidth+2]; 398 aBorderLine.LineDistance = aWidths[nNWidth+3]; 399 } 400 else 401 { 402 lcl_frmitems_setXMLBorderWidth( aBorderLine, nWidth, bDouble ); 403 } 404 } 405 else 406 { 407 lcl_frmitems_setXMLBorderWidth( aBorderLine, 0, bDouble ); 408 } 409 410 // set color 411 if( bHasColor ) 412 aBorderLine.Color = (sal_Int32)aColor.GetRGBColor(); 413 414 rValue <<= aBorderLine; 415 return sal_True; 416 } 417 418 sal_Bool XMLBorderHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const 419 { 420 OUStringBuffer aOut; 421 422 table::BorderLine aBorderLine; 423 if(!(rValue >>= aBorderLine)) 424 return sal_False; 425 426 sal_Int32 nWidth = aBorderLine.OuterLineWidth; 427 const sal_uInt16 nDistance = aBorderLine.LineDistance; 428 if( 0 != nDistance ) 429 { 430 nWidth += nDistance; 431 nWidth += aBorderLine.InnerLineWidth; 432 } 433 434 if( nWidth == 0 ) 435 { 436 aOut.append( GetXMLToken( XML_NONE ) ); 437 } 438 else 439 { 440 rUnitConverter.convertMeasure( aOut, nWidth ); 441 442 aOut.append( sal_Unicode( ' ' ) ); 443 444 aOut.append( GetXMLToken((0 == nDistance) ? XML_SOLID : XML_DOUBLE) ); 445 446 aOut.append( sal_Unicode( ' ' ) ); 447 448 rUnitConverter.convertColor( aOut, aBorderLine.Color ); 449 } 450 451 rStrExpValue = aOut.makeStringAndClear(); 452 453 return sal_True; 454 } 455