Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 : #include <ConversionHelper.hxx>
20 : #include <com/sun/star/table/BorderLine2.hpp>
21 : #include <com/sun/star/table/BorderLineStyle.hpp>
22 : #include <com/sun/star/lang/Locale.hpp>
23 : #include <com/sun/star/text/HoriOrientation.hpp>
24 : #include <com/sun/star/style/NumberingType.hpp>
25 : #include <editeng/borderline.hxx>
26 : #include <ooxml/resourceids.hxx>
27 : #include <rtl/ustrbuf.hxx>
28 : #include <tools/color.hxx>
29 : #include <tools/mapunit.hxx>
30 : #include <algorithm>
31 : #include <functional>
32 :
33 : using namespace com::sun::star;
34 : using namespace com::sun::star::table::BorderLineStyle;
35 :
36 : namespace writerfilter {
37 : namespace dmapper{
38 : namespace ConversionHelper{
39 :
40 0 : sal_Int32 MakeBorderLine( sal_Int32 nSprmValue, table::BorderLine2& rToFill )
41 : {
42 : //TODO: Lines are always solid
43 : //Border
44 : //borders are defined as:
45 : // 0x XX XX XX XX
46 : // || || || ||
47 : // || || || ---- Line width in 1/8 pt
48 : // || || ||
49 : // || || ------- Line type: 0 - none 1 - single ... 25 - engrave 3D and 64 - 230 page borders
50 : // || ||
51 : // || ---------- Line color
52 : // ||
53 : // ------------- seven bits line space
54 : // -------------- first bit: with shading
55 0 : sal_Int16 nLineThicknessTwip = (sal_Int16)((nSprmValue & 0xff) * 20)/8L ;
56 0 : sal_Int32 nLineType = ((nSprmValue & 0xff00) >> 8);
57 0 : sal_Int32 nLineColor = (nSprmValue & 0xff0000)>>16;
58 0 : sal_Int32 nLineDistance = (((nSprmValue & 0x3f000000)>>24) * 2540 + 36)/72L;
59 0 : MakeBorderLine( nLineThicknessTwip, nLineType, nLineColor, rToFill, false);
60 0 : return nLineDistance;
61 : }
62 0 : void MakeBorderLine( sal_Int32 nLineThickness, sal_Int32 nLineType,
63 : sal_Int32 nLineColor,
64 : table::BorderLine2& rToFill, bool bIsOOXML )
65 : {
66 : static const sal_Int32 aBorderDefColor[] =
67 : {
68 : // The first item means automatic color (COL_AUTO), but we
69 : // do not use it anyway (see the next statement) .-)
70 : 0, COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
71 : COL_LIGHTMAGENTA, COL_LIGHTRED, COL_YELLOW, COL_WHITE, COL_BLUE,
72 : COL_CYAN, COL_GREEN, COL_MAGENTA, COL_RED, COL_BROWN, COL_GRAY,
73 : COL_LIGHTGRAY
74 : };
75 : //no auto color for borders
76 0 : if(!nLineColor)
77 0 : ++nLineColor;
78 0 : if(!bIsOOXML && sal::static_int_cast<sal_uInt32>(nLineColor) < SAL_N_ELEMENTS(aBorderDefColor))
79 0 : nLineColor = aBorderDefColor[nLineColor];
80 :
81 : // Map to our border types, we should use of one equal line
82 : // thickness, or one of smaller thickness. If too small we
83 : // can make the defecit up in additional white space or
84 : // object size
85 : ::editeng::SvxBorderStyle const nLineStyle(
86 0 : ::editeng::ConvertBorderStyleFromWord(nLineType));
87 0 : rToFill.LineStyle = nLineStyle;
88 : double const fConverted( (NONE == nLineStyle) ? 0.0 :
89 : ::editeng::ConvertBorderWidthFromWord(nLineStyle, nLineThickness,
90 0 : nLineType));
91 0 : rToFill.LineWidth = convertTwipToMM100(fConverted);
92 0 : rToFill.Color = nLineColor;
93 0 : }
94 :
95 : namespace {
96 0 : void lcl_SwapQuotesInField(OUString &rFmt)
97 : {
98 : //Swap unescaped " and ' with ' and "
99 0 : sal_Int32 nLen = rFmt.getLength();
100 0 : OUStringBuffer aBuffer( rFmt.getStr() );
101 0 : const sal_Unicode* pFmt = rFmt.getStr();
102 0 : for (sal_Int32 nI = 0; nI < nLen; ++nI)
103 : {
104 0 : if ((pFmt[nI] == '\"') && (!nI || pFmt[nI-1] != '\\'))
105 0 : aBuffer[nI] = '\'';
106 0 : else if ((pFmt[nI] == '\'') && (!nI || pFmt[nI-1] != '\\'))
107 0 : aBuffer[nI] = '\"';
108 : }
109 0 : rFmt = aBuffer.makeStringAndClear();
110 0 : }
111 0 : bool lcl_IsNotAM(OUString& rFmt, sal_Int32 nPos)
112 : {
113 : return (
114 0 : (nPos == rFmt.getLength() - 1) ||
115 : (
116 0 : (rFmt[nPos+1] != 'M') &&
117 0 : (rFmt[nPos+1] != 'm')
118 : )
119 0 : );
120 : }
121 : }
122 :
123 0 : OUString ConvertMSFormatStringToSO(
124 : const OUString& rFormat, lang::Locale& rLocale, bool bHijri)
125 : {
126 0 : OUString sFormat(rFormat);
127 0 : lcl_SwapQuotesInField(sFormat);
128 :
129 : //#102782#, #102815#, #108341# & #111944# have to work at the same time :-)
130 0 : bool bForceJapanese(false);
131 0 : bool bForceNatNum(false);
132 0 : sal_Int32 nLen = sFormat.getLength();
133 0 : sal_Int32 nI = 0;
134 : // const sal_Unicode* pFormat = sFormat.getStr();
135 0 : OUStringBuffer aNewFormat( sFormat );
136 0 : while (nI < nLen)
137 : {
138 0 : if (aNewFormat[nI] == '\\')
139 0 : nI++;
140 0 : else if (aNewFormat[nI] == '\"')
141 : {
142 0 : ++nI;
143 : //While not at the end and not at an unescaped end quote
144 0 : while ((nI < nLen) && (!(aNewFormat[nI] == '\"') && (aNewFormat[nI-1] != '\\')))
145 0 : ++nI;
146 : }
147 : else //normal unquoted section
148 : {
149 0 : sal_Unicode nChar = aNewFormat[nI];
150 0 : if (nChar == 'O')
151 : {
152 0 : aNewFormat[nI] = 'M';
153 0 : bForceNatNum = true;
154 : }
155 0 : else if (nChar == 'o')
156 : {
157 0 : aNewFormat[nI] = 'm';
158 0 : bForceNatNum = true;
159 : }
160 0 : else if ((nChar == 'A') && lcl_IsNotAM(sFormat, nI))
161 : {
162 0 : aNewFormat[nI] = 'D';
163 0 : bForceNatNum = true;
164 : }
165 0 : else if ((nChar == 'g') || (nChar == 'G'))
166 0 : bForceJapanese = true;
167 0 : else if ((nChar == 'a') && lcl_IsNotAM(sFormat, nI))
168 0 : bForceJapanese = true;
169 0 : else if (nChar == 'E')
170 : {
171 0 : if ((nI != nLen-1) && (aNewFormat[nI+1] == 'E'))
172 : {
173 : //todo: this cannot be the right way to replace a part of the string!
174 0 : aNewFormat[nI] = 'Y';
175 0 : aNewFormat[nI + 1] = 'Y';
176 0 : aNewFormat.insert(nI + 2, "YY");
177 0 : nLen+=2;
178 0 : nI+=3;
179 : }
180 0 : bForceJapanese = true;
181 : }
182 0 : else if (nChar == 'e')
183 : {
184 0 : if ((nI != nLen-1) && (aNewFormat[nI+1] == 'e'))
185 : {
186 : //todo: this cannot be the right way to replace a part of the string!
187 0 : aNewFormat[nI] = 'y';
188 0 : aNewFormat[nI + 1] = 'y';
189 0 : aNewFormat.insert(nI + 2, "yy");
190 0 : nLen+=2;
191 0 : nI+=3;
192 : }
193 0 : bForceJapanese = true;
194 : }
195 0 : else if (nChar == '/')
196 : {
197 : // MM We have to escape '/' in case it's used as a char
198 : //todo: this cannot be the right way to replace a part of the string!
199 0 : aNewFormat[nI] = '\\';
200 0 : aNewFormat.insert(nI + 1, "/");
201 0 : nI++;
202 0 : nLen++;
203 : }
204 : }
205 0 : ++nI;
206 : }
207 :
208 0 : if (bForceNatNum)
209 0 : bForceJapanese = true;
210 :
211 0 : if (bForceJapanese)
212 : {
213 0 : rLocale.Language = "ja";
214 0 : rLocale.Country = "JP";
215 : }
216 :
217 0 : if (bForceNatNum)
218 : {
219 0 : aNewFormat.insert( 0, "[NatNum1][$-411]");
220 : }
221 :
222 0 : if (bHijri)
223 : {
224 0 : aNewFormat.insert( 0, "[~hijri]");
225 : }
226 0 : return aNewFormat.makeStringAndClear();
227 :
228 : }
229 :
230 0 : sal_Int32 convertTwipToMM100(sal_Int32 _t)
231 : {
232 0 : return ::convertTwipToMm100( _t );
233 : }
234 :
235 0 : sal_uInt32 convertTwipToMM100Unsigned(sal_Int32 _t)
236 : {
237 0 : if( _t < 0 )
238 0 : return 0;
239 : // It appears that MSO handles large twip values specially, probably legacy 16bit handling,
240 : // anything that's bigger than 32767 appears to be simply ignored.
241 0 : if( _t >= 0x8000 )
242 0 : return 0;
243 0 : return ::convertTwipToMm100( _t );
244 : }
245 :
246 0 : sal_Int32 convertEMUToMM100(sal_Int32 _t)
247 : {
248 0 : return _t / 360;
249 : }
250 :
251 0 : sal_Int16 convertTableJustification( sal_Int32 nIntValue )
252 : {
253 0 : sal_Int16 nOrient = text::HoriOrientation::LEFT_AND_WIDTH;
254 0 : switch( nIntValue )
255 : {
256 0 : case 1 : nOrient = text::HoriOrientation::CENTER; break;
257 0 : case 2 : nOrient = text::HoriOrientation::RIGHT; break;
258 : case 0 :
259 : //no break
260 : default:;
261 :
262 : }
263 0 : return nOrient;
264 : }
265 :
266 0 : sal_Int16 ConvertNumberingType(sal_Int32 nFmt)
267 : {
268 : sal_Int16 nRet;
269 0 : switch(nFmt)
270 : {
271 : case NS_ooxml::LN_Value_ST_NumberFormat_decimal:
272 : case 0:
273 0 : nRet = style::NumberingType::ARABIC;
274 0 : break;
275 : case NS_ooxml::LN_Value_ST_NumberFormat_upperRoman:
276 : case 1:
277 0 : nRet = style::NumberingType::ROMAN_UPPER;
278 0 : break;
279 : case NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman:
280 : case 2:
281 0 : nRet = style::NumberingType::ROMAN_LOWER;
282 0 : break;
283 : case 3:
284 0 : nRet = style::NumberingType::CHARS_UPPER_LETTER_N;
285 0 : break;
286 : case 4:
287 0 : nRet = style::NumberingType::CHARS_LOWER_LETTER_N;
288 0 : break;
289 : case 5:
290 0 : nRet = style::NumberingType::ARABIC;
291 0 : break;//ORDINAL
292 : case NS_ooxml::LN_Value_ST_NumberFormat_bullet:
293 : case 23:
294 : case 25:
295 0 : nRet = style::NumberingType::CHAR_SPECIAL;
296 0 : break;
297 : case NS_ooxml::LN_Value_ST_NumberFormat_none:
298 : case 255:
299 0 : nRet = style::NumberingType::NUMBER_NONE;
300 0 : break;
301 : case NS_ooxml::LN_Value_ST_NumberFormat_upperLetter:
302 0 : nRet = style::NumberingType::CHARS_UPPER_LETTER;
303 0 : break;
304 : case NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter:
305 0 : nRet = style::NumberingType::CHARS_LOWER_LETTER;
306 0 : break;
307 : case NS_ooxml::LN_Value_ST_NumberFormat_iroha:
308 0 : nRet = style::NumberingType::IROHA_HALFWIDTH_JA;
309 0 : break;
310 : case NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth:
311 0 : nRet = style::NumberingType::IROHA_FULLWIDTH_JA;
312 0 : break;
313 : case NS_ooxml::LN_Value_ST_NumberFormat_aiueo:
314 0 : nRet = style::NumberingType::AIU_HALFWIDTH_JA;
315 0 : break;
316 : case NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth:
317 0 : nRet = style::NumberingType::AIU_FULLWIDTH_JA;
318 0 : break;
319 : case NS_ooxml::LN_Value_ST_NumberFormat_hebrew2:
320 0 : nRet = style::NumberingType::CHARS_HEBREW;
321 0 : break;
322 : case NS_ooxml::LN_Value_ST_NumberFormat_thaiLetters:
323 0 : nRet = style::NumberingType::CHARS_THAI;
324 0 : break;
325 : case NS_ooxml::LN_Value_ST_NumberFormat_russianLower:
326 0 : nRet = style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU;
327 0 : break;
328 : case NS_ooxml::LN_Value_ST_NumberFormat_russianUpper:
329 0 : nRet = style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU;
330 0 : break;
331 : case NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese:
332 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle:
333 0 : nRet = style::NumberingType::CIRCLE_NUMBER;
334 0 : break;
335 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional:
336 0 : nRet = style::NumberingType::TIAN_GAN_ZH;
337 0 : break;
338 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac:
339 0 : nRet = style::NumberingType::DI_ZI_ZH;
340 0 : break;
341 : case NS_ooxml::LN_Value_ST_NumberFormat_ganada:
342 0 : nRet = style::NumberingType::HANGUL_SYLLABLE_KO;
343 0 : break;
344 : case NS_ooxml::LN_Value_ST_NumberFormat_chosung:
345 0 : nRet = style::NumberingType::HANGUL_JAMO_KO;
346 0 : break;
347 : case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital:
348 : case NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting:
349 : case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2:
350 0 : nRet = style::NumberingType::NUMBER_HANGUL_KO;
351 0 : break;
352 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional:
353 0 : nRet = style::NumberingType::NUMBER_UPPER_ZH_TW;
354 0 : break;
355 : case NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha:
356 0 : nRet = style::NumberingType::CHARS_ARABIC;
357 0 : break;
358 : case NS_ooxml::LN_Value_ST_NumberFormat_hindiVowels:
359 0 : nRet = style::NumberingType::CHARS_NEPALI;
360 0 : break;
361 : case NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal:
362 0 : nRet = style::NumberingType::NUMBER_TRADITIONAL_JA;
363 0 : break;
364 : case NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting:
365 : case NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting:
366 : case NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting:
367 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital:
368 : case NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand:
369 0 : nRet = style::NumberingType::NUMBER_LOWER_ZH;
370 0 : break;
371 : case NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified:
372 0 : nRet = style::NumberingType::NUMBER_UPPER_ZH;
373 0 : break;
374 : case NS_ooxml::LN_Value_ST_NumberFormat_hebrew1:
375 : //91726
376 0 : nRet = style::NumberingType::CHARS_HEBREW;
377 0 : break;
378 0 : default: nRet = style::NumberingType::ARABIC;
379 : }
380 : /* TODO: Lots of additional values are available - some are supported in the I18 framework
381 : NS_ooxml::LN_Value_ST_NumberFormat_ordinal = 91682;
382 : NS_ooxml::LN_Value_ST_NumberFormat_cardinalText = 91683;
383 : NS_ooxml::LN_Value_ST_NumberFormat_ordinalText = 91684;
384 : NS_ooxml::LN_Value_ST_NumberFormat_hex = 91685;
385 : NS_ooxml::LN_Value_ST_NumberFormat_chicago = 91686;
386 : NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth = 91691;
387 : NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth = 91692;
388 : NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand = 91694;
389 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircle = 91695;
390 : NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2 = 91696;
391 : NS_ooxml::LN_Value_ST_NumberFormat_decimalZero = 91699;
392 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop = 91703;
393 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen = 91704;
394 : NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional = 91709;
395 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand = 91712;
396 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital = 91713;
397 : NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified = 91715;
398 : NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand = 91716;
399 : NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal = 91719;
400 : NS_ooxml::LN_Value_ST_NumberFormat_vietnameseCounting = 91721;
401 : NS_ooxml::LN_Value_ST_NumberFormat_numberInDash = 91725;
402 : NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad:
403 : NS_ooxml::LN_Value_ST_NumberFormat_hindiConsonants = 91731;
404 : NS_ooxml::LN_Value_ST_NumberFormat_hindiNumbers = 91732;
405 : NS_ooxml::LN_Value_ST_NumberFormat_hindiCounting = 91733;
406 : NS_ooxml::LN_Value_ST_NumberFormat_thaiNumbers = 91735;
407 : NS_ooxml::LN_Value_ST_NumberFormat_thaiCounting = 91736;*/
408 0 : return nRet;
409 : }
410 :
411 0 : com::sun::star::util::DateTime ConvertDateStringToDateTime( const OUString& rDateTime )
412 : {
413 0 : com::sun::star::util::DateTime aDateTime;
414 : //xsd::DateTime in the format [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] example: 2008-01-21T10:42:00Z
415 : //OUString getToken( sal_Int32 token, sal_Unicode cTok, sal_Int32& index ) const SAL_THROW(())
416 0 : sal_Int32 nIndex = 0;
417 0 : OUString sDate = rDateTime.getToken( 0, 'T', nIndex );
418 : // HACK: this is broken according to the spec, but MSOffice always treats the time as local,
419 : // and writes it as Z (=UTC+0)
420 0 : OUString sTime = rDateTime.getToken( 0, 'Z', nIndex );
421 0 : nIndex = 0;
422 0 : aDateTime.Year = sal_uInt16( sDate.getToken( 0, '-', nIndex ).toInt32() );
423 0 : aDateTime.Month = sal_uInt16( sDate.getToken( 0, '-', nIndex ).toInt32() );
424 0 : if (nIndex != -1)
425 0 : aDateTime.Day = sal_uInt16( sDate.copy( nIndex ).toInt32() );
426 :
427 0 : nIndex = 0;
428 0 : aDateTime.Hours = sal_uInt16( sTime.getToken( 0, ':', nIndex ).toInt32() );
429 0 : aDateTime.Minutes = sal_uInt16( sTime.getToken( 0, ':', nIndex ).toInt32() );
430 0 : if (nIndex != -1)
431 0 : aDateTime.Seconds = sal_uInt16( sTime.copy( nIndex ).toInt32() );
432 :
433 0 : return aDateTime;
434 : }
435 :
436 :
437 : } // namespace ConversionHelper
438 : } //namespace dmapper
439 : } //namespace writerfilter
440 :
441 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|