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 
35 namespace writerfilter {
36 namespace dmapper{
37 namespace ConversionHelper{
38 
39 /// Convert OOXML border style to WW8 that editeng can handle.
lcl_convertBorderStyleFromToken(sal_Int32 nOOXMLType)40 static sal_Int32 lcl_convertBorderStyleFromToken(sal_Int32 nOOXMLType)
41 {
42     switch (nOOXMLType)
43     {
44         case NS_ooxml::LN_Value_ST_Border_nil: return 255;
45         case NS_ooxml::LN_Value_ST_Border_none: return 0;
46         case NS_ooxml::LN_Value_ST_Border_single: return 1;
47         case NS_ooxml::LN_Value_ST_Border_thick: return 2;
48         case NS_ooxml::LN_Value_ST_Border_double: return 3;
49         case NS_ooxml::LN_Value_ST_Border_dotted: return 6;
50         case NS_ooxml::LN_Value_ST_Border_dashed: return 7;
51         case NS_ooxml::LN_Value_ST_Border_dotDash: return 8;
52         case NS_ooxml::LN_Value_ST_Border_dotDotDash: return 9;
53         case NS_ooxml::LN_Value_ST_Border_triple: return 10;
54         case NS_ooxml::LN_Value_ST_Border_thinThickSmallGap: return 11;
55         case NS_ooxml::LN_Value_ST_Border_thickThinSmallGap: return 12;
56         case NS_ooxml::LN_Value_ST_Border_thinThickThinSmallGap: return 13;
57         case NS_ooxml::LN_Value_ST_Border_thinThickMediumGap: return 14;
58         case NS_ooxml::LN_Value_ST_Border_thickThinMediumGap: return 15;
59         case NS_ooxml::LN_Value_ST_Border_thinThickThinMediumGap: return 16;
60         case NS_ooxml::LN_Value_ST_Border_thinThickLargeGap: return 17;
61         case NS_ooxml::LN_Value_ST_Border_thickThinLargeGap: return 18;
62         case NS_ooxml::LN_Value_ST_Border_thinThickThinLargeGap: return 19;
63         case NS_ooxml::LN_Value_ST_Border_wave: return 20;
64         case NS_ooxml::LN_Value_ST_Border_doubleWave: return 21;
65         case NS_ooxml::LN_Value_ST_Border_dashSmallGap: return 22;
66         case NS_ooxml::LN_Value_ST_Border_dashDotStroked: return 23;
67         case NS_ooxml::LN_Value_ST_Border_threeDEmboss: return 24;
68         case NS_ooxml::LN_Value_ST_Border_threeDEngrave: return 25;
69         case NS_ooxml::LN_Value_ST_Border_outset: return 26;
70         case NS_ooxml::LN_Value_ST_Border_inset: return 27;
71         case NS_ooxml::LN_Value_ST_Border_apples: return 64;
72         case NS_ooxml::LN_Value_ST_Border_archedScallops: return 65;
73         case NS_ooxml::LN_Value_ST_Border_babyPacifier: return 66;
74         case NS_ooxml::LN_Value_ST_Border_babyRattle: return 67;
75         case NS_ooxml::LN_Value_ST_Border_balloons3Colors: return 68;
76         case NS_ooxml::LN_Value_ST_Border_balloonsHotAir: return 69;
77         case NS_ooxml::LN_Value_ST_Border_basicBlackDashes: return 70;
78         case NS_ooxml::LN_Value_ST_Border_basicBlackDots: return 71;
79         case NS_ooxml::LN_Value_ST_Border_basicBlackSquares: return 72;
80         case NS_ooxml::LN_Value_ST_Border_basicThinLines: return 73;
81         case NS_ooxml::LN_Value_ST_Border_basicWhiteDashes: return 74;
82         case NS_ooxml::LN_Value_ST_Border_basicWhiteDots: return 75;
83         case NS_ooxml::LN_Value_ST_Border_basicWhiteSquares: return 76;
84         case NS_ooxml::LN_Value_ST_Border_basicWideInline: return 77;
85         case NS_ooxml::LN_Value_ST_Border_basicWideMidline: return 78;
86         case NS_ooxml::LN_Value_ST_Border_basicWideOutline: return 79;
87         case NS_ooxml::LN_Value_ST_Border_bats: return 80;
88         case NS_ooxml::LN_Value_ST_Border_birds: return 81;
89         case NS_ooxml::LN_Value_ST_Border_birdsFlight: return 82;
90         case NS_ooxml::LN_Value_ST_Border_cabins: return 83;
91         case NS_ooxml::LN_Value_ST_Border_cakeSlice: return 84;
92         case NS_ooxml::LN_Value_ST_Border_candyCorn: return 85;
93         case NS_ooxml::LN_Value_ST_Border_celticKnotwork: return 86;
94         case NS_ooxml::LN_Value_ST_Border_certificateBanner: return 87;
95         case NS_ooxml::LN_Value_ST_Border_chainLink: return 88;
96         case NS_ooxml::LN_Value_ST_Border_champagneBottle: return 89;
97         case NS_ooxml::LN_Value_ST_Border_checkedBarBlack: return 90;
98         case NS_ooxml::LN_Value_ST_Border_checkedBarColor: return 91;
99         case NS_ooxml::LN_Value_ST_Border_checkered: return 92;
100         case NS_ooxml::LN_Value_ST_Border_christmasTree: return 93;
101         case NS_ooxml::LN_Value_ST_Border_circlesLines: return 94;
102         case NS_ooxml::LN_Value_ST_Border_circlesRectangles: return 95;
103         case NS_ooxml::LN_Value_ST_Border_classicalWave: return 96;
104         case NS_ooxml::LN_Value_ST_Border_clocks: return 97;
105         case NS_ooxml::LN_Value_ST_Border_compass: return 98;
106         case NS_ooxml::LN_Value_ST_Border_confetti: return 99;
107         case NS_ooxml::LN_Value_ST_Border_confettiGrays: return 100;
108         case NS_ooxml::LN_Value_ST_Border_confettiOutline: return 101;
109         case NS_ooxml::LN_Value_ST_Border_confettiStreamers: return 102;
110         case NS_ooxml::LN_Value_ST_Border_confettiWhite: return 103;
111         case NS_ooxml::LN_Value_ST_Border_cornerTriangles: return 104;
112         case NS_ooxml::LN_Value_ST_Border_couponCutoutDashes: return 105;
113         case NS_ooxml::LN_Value_ST_Border_couponCutoutDots: return 106;
114         case NS_ooxml::LN_Value_ST_Border_crazyMaze: return 107;
115         case NS_ooxml::LN_Value_ST_Border_creaturesButterfly: return 108;
116         case NS_ooxml::LN_Value_ST_Border_creaturesFish: return 109;
117         case NS_ooxml::LN_Value_ST_Border_creaturesInsects: return 110;
118         case NS_ooxml::LN_Value_ST_Border_creaturesLadyBug: return 111;
119         case NS_ooxml::LN_Value_ST_Border_crossStitch: return 112;
120         case NS_ooxml::LN_Value_ST_Border_cup: return 113;
121         case NS_ooxml::LN_Value_ST_Border_decoArch: return 114;
122         case NS_ooxml::LN_Value_ST_Border_decoArchColor: return 115;
123         case NS_ooxml::LN_Value_ST_Border_decoBlocks: return 116;
124         case NS_ooxml::LN_Value_ST_Border_diamondsGray: return 117;
125         case NS_ooxml::LN_Value_ST_Border_doubleD: return 118;
126         case NS_ooxml::LN_Value_ST_Border_doubleDiamonds: return 119;
127         case NS_ooxml::LN_Value_ST_Border_earth1: return 120;
128         case NS_ooxml::LN_Value_ST_Border_earth2: return 121;
129         case NS_ooxml::LN_Value_ST_Border_eclipsingSquares1: return 122;
130         case NS_ooxml::LN_Value_ST_Border_eclipsingSquares2: return 123;
131         case NS_ooxml::LN_Value_ST_Border_eggsBlack: return 124;
132         case NS_ooxml::LN_Value_ST_Border_fans: return 125;
133         case NS_ooxml::LN_Value_ST_Border_film: return 126;
134         case NS_ooxml::LN_Value_ST_Border_firecrackers: return 127;
135         case NS_ooxml::LN_Value_ST_Border_flowersBlockPrint: return 128;
136         case NS_ooxml::LN_Value_ST_Border_flowersDaisies: return 129;
137         case NS_ooxml::LN_Value_ST_Border_flowersModern1: return 130;
138         case NS_ooxml::LN_Value_ST_Border_flowersModern2: return 131;
139         case NS_ooxml::LN_Value_ST_Border_flowersPansy: return 132;
140         case NS_ooxml::LN_Value_ST_Border_flowersRedRose: return 133;
141         case NS_ooxml::LN_Value_ST_Border_flowersRoses: return 134;
142         case NS_ooxml::LN_Value_ST_Border_flowersTeacup: return 135;
143         case NS_ooxml::LN_Value_ST_Border_flowersTiny: return 136;
144         case NS_ooxml::LN_Value_ST_Border_gems: return 137;
145         case NS_ooxml::LN_Value_ST_Border_gingerbreadMan: return 138;
146         case NS_ooxml::LN_Value_ST_Border_gradient: return 139;
147         case NS_ooxml::LN_Value_ST_Border_handmade1: return 140;
148         case NS_ooxml::LN_Value_ST_Border_handmade2: return 141;
149         case NS_ooxml::LN_Value_ST_Border_heartBalloon: return 142;
150         case NS_ooxml::LN_Value_ST_Border_heartGray: return 143;
151         case NS_ooxml::LN_Value_ST_Border_hearts: return 144;
152         case NS_ooxml::LN_Value_ST_Border_heebieJeebies: return 145;
153         case NS_ooxml::LN_Value_ST_Border_holly: return 146;
154         case NS_ooxml::LN_Value_ST_Border_houseFunky: return 147;
155         case NS_ooxml::LN_Value_ST_Border_hypnotic: return 148;
156         case NS_ooxml::LN_Value_ST_Border_iceCreamCones: return 149;
157         case NS_ooxml::LN_Value_ST_Border_lightBulb: return 150;
158         case NS_ooxml::LN_Value_ST_Border_lightning1: return 151;
159         case NS_ooxml::LN_Value_ST_Border_lightning2: return 152;
160         case NS_ooxml::LN_Value_ST_Border_mapPins: return 153;
161         case NS_ooxml::LN_Value_ST_Border_mapleLeaf: return 154;
162         case NS_ooxml::LN_Value_ST_Border_mapleMuffins: return 155;
163         case NS_ooxml::LN_Value_ST_Border_marquee: return 156;
164         case NS_ooxml::LN_Value_ST_Border_marqueeToothed: return 157;
165         case NS_ooxml::LN_Value_ST_Border_moons: return 158;
166         case NS_ooxml::LN_Value_ST_Border_mosaic: return 159;
167         case NS_ooxml::LN_Value_ST_Border_musicNotes: return 160;
168         case NS_ooxml::LN_Value_ST_Border_northwest: return 161;
169         case NS_ooxml::LN_Value_ST_Border_ovals: return 162;
170         case NS_ooxml::LN_Value_ST_Border_packages: return 163;
171         case NS_ooxml::LN_Value_ST_Border_palmsBlack: return 164;
172         case NS_ooxml::LN_Value_ST_Border_palmsColor: return 165;
173         case NS_ooxml::LN_Value_ST_Border_paperClips: return 166;
174         case NS_ooxml::LN_Value_ST_Border_papyrus: return 167;
175         case NS_ooxml::LN_Value_ST_Border_partyFavor: return 168;
176         case NS_ooxml::LN_Value_ST_Border_partyGlass: return 169;
177         case NS_ooxml::LN_Value_ST_Border_pencils: return 170;
178         case NS_ooxml::LN_Value_ST_Border_people: return 171;
179         case NS_ooxml::LN_Value_ST_Border_peopleWaving: return 172;
180         case NS_ooxml::LN_Value_ST_Border_peopleHats: return 173;
181         case NS_ooxml::LN_Value_ST_Border_poinsettias: return 174;
182         case NS_ooxml::LN_Value_ST_Border_postageStamp: return 175;
183         case NS_ooxml::LN_Value_ST_Border_pumpkin1: return 176;
184         case NS_ooxml::LN_Value_ST_Border_pushPinNote2: return 177;
185         case NS_ooxml::LN_Value_ST_Border_pushPinNote1: return 178;
186         case NS_ooxml::LN_Value_ST_Border_pyramids: return 179;
187         case NS_ooxml::LN_Value_ST_Border_pyramidsAbove: return 180;
188         case NS_ooxml::LN_Value_ST_Border_quadrants: return 181;
189         case NS_ooxml::LN_Value_ST_Border_rings: return 182;
190         case NS_ooxml::LN_Value_ST_Border_safari: return 183;
191         case NS_ooxml::LN_Value_ST_Border_sawtooth: return 184;
192         case NS_ooxml::LN_Value_ST_Border_sawtoothGray: return 185;
193         case NS_ooxml::LN_Value_ST_Border_scaredCat: return 186;
194         case NS_ooxml::LN_Value_ST_Border_seattle: return 187;
195         case NS_ooxml::LN_Value_ST_Border_shadowedSquares: return 188;
196         case NS_ooxml::LN_Value_ST_Border_sharksTeeth: return 189;
197         case NS_ooxml::LN_Value_ST_Border_shorebirdTracks: return 190;
198         case NS_ooxml::LN_Value_ST_Border_skyrocket: return 191;
199         case NS_ooxml::LN_Value_ST_Border_snowflakeFancy: return 192;
200         case NS_ooxml::LN_Value_ST_Border_snowflakes: return 193;
201         case NS_ooxml::LN_Value_ST_Border_sombrero: return 194;
202         case NS_ooxml::LN_Value_ST_Border_southwest: return 195;
203         case NS_ooxml::LN_Value_ST_Border_stars: return 196;
204         case NS_ooxml::LN_Value_ST_Border_starsTop: return 197;
205         case NS_ooxml::LN_Value_ST_Border_stars3d: return 198;
206         case NS_ooxml::LN_Value_ST_Border_starsBlack: return 199;
207         case NS_ooxml::LN_Value_ST_Border_starsShadowed: return 200;
208         case NS_ooxml::LN_Value_ST_Border_sun: return 201;
209         case NS_ooxml::LN_Value_ST_Border_swirligig: return 202;
210         case NS_ooxml::LN_Value_ST_Border_tornPaper: return 203;
211         case NS_ooxml::LN_Value_ST_Border_tornPaperBlack: return 204;
212         case NS_ooxml::LN_Value_ST_Border_trees: return 205;
213         case NS_ooxml::LN_Value_ST_Border_triangleParty: return 206;
214         case NS_ooxml::LN_Value_ST_Border_triangles: return 207;
215         case NS_ooxml::LN_Value_ST_Border_tribal1: return 208;
216         case NS_ooxml::LN_Value_ST_Border_tribal2: return 209;
217         case NS_ooxml::LN_Value_ST_Border_tribal3: return 210;
218         case NS_ooxml::LN_Value_ST_Border_tribal4: return 211;
219         case NS_ooxml::LN_Value_ST_Border_tribal5: return 212;
220         case NS_ooxml::LN_Value_ST_Border_tribal6: return 213;
221         case NS_ooxml::LN_Value_ST_Border_twistedLines1: return 214;
222         case NS_ooxml::LN_Value_ST_Border_twistedLines2: return 215;
223         case NS_ooxml::LN_Value_ST_Border_vine: return 216;
224         case NS_ooxml::LN_Value_ST_Border_waveline: return 217;
225         case NS_ooxml::LN_Value_ST_Border_weavingAngles: return 218;
226         case NS_ooxml::LN_Value_ST_Border_weavingBraid: return 219;
227         case NS_ooxml::LN_Value_ST_Border_weavingRibbon: return 220;
228         case NS_ooxml::LN_Value_ST_Border_weavingStrips: return 221;
229         case NS_ooxml::LN_Value_ST_Border_whiteFlowers: return 222;
230         case NS_ooxml::LN_Value_ST_Border_woodwork: return 223;
231         case NS_ooxml::LN_Value_ST_Border_xIllusions: return 224;
232         case NS_ooxml::LN_Value_ST_Border_zanyTriangles: return 225;
233         case NS_ooxml::LN_Value_ST_Border_zigZag: return 226;
234         case NS_ooxml::LN_Value_ST_Border_zigZagStitch: return 227;
235         default: break;
236     }
237     return 0;
238 }
239 
MakeBorderLine(sal_Int32 nLineThickness,sal_Int32 nLineToken,sal_Int32 nLineColor,table::BorderLine2 & rToFill,bool bIsOOXML)240 void MakeBorderLine( sal_Int32 nLineThickness,   sal_Int32 nLineToken,
241                                             sal_Int32 nLineColor,
242                                             table::BorderLine2& rToFill, bool bIsOOXML )
243 {
244     static const Color aBorderDefColor[] =
245     {
246         // The first item means automatic color (COL_AUTO), but we
247         // do not use it anyway (see the next statement) .-)
248         // See also GetLineIndex in sw/source/filter/ww8/ww8par6.cxx
249         COL_AUTO, COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
250         COL_LIGHTMAGENTA, COL_LIGHTRED, COL_YELLOW, COL_WHITE, COL_BLUE,
251         COL_CYAN, COL_GREEN, COL_MAGENTA, COL_RED, COL_BROWN, COL_GRAY,
252         COL_LIGHTGRAY
253     };
254     if(!bIsOOXML && sal::static_int_cast<sal_uInt32>(nLineColor) < SAL_N_ELEMENTS(aBorderDefColor))
255         nLineColor = sal_Int32(aBorderDefColor[nLineColor]);
256     //no auto color for borders
257     if (nLineColor == sal_Int32(COL_AUTO))
258         nLineColor = sal_Int32(COL_BLACK);
259 
260     sal_Int32 nLineType = lcl_convertBorderStyleFromToken(nLineToken);
261 
262     // Map to our border types, we should use of one equal line
263     // thickness, or one of smaller thickness. If too small we
264     // can make the deficit up in additional white space or
265     // object size
266     SvxBorderLineStyle const nLineStyle(
267             ::editeng::ConvertBorderStyleFromWord(nLineType));
268     rToFill.LineStyle = static_cast<sal_Int16>(nLineStyle);
269     double const fConverted( (SvxBorderLineStyle::NONE == nLineStyle) ? 0.0 :
270         ::editeng::ConvertBorderWidthFromWord(nLineStyle, nLineThickness,
271             nLineType));
272     rToFill.LineWidth = convertTwipToMM100(fConverted);
273     rToFill.Color = nLineColor;
274 }
275 
276 namespace {
lcl_SwapQuotesInField(OUString & rFmt)277 void lcl_SwapQuotesInField(OUString &rFmt)
278 {
279     //Swap unescaped " and ' with ' and "
280     sal_Int32 nLen = rFmt.getLength();
281     OUStringBuffer aBuffer( rFmt );
282     const sal_Unicode* pFmt = rFmt.getStr();
283     for (sal_Int32 nI = 0; nI < nLen; ++nI)
284     {
285         if ((pFmt[nI] == '\"') && (!nI || pFmt[nI-1] != '\\'))
286             aBuffer[nI] = '\'';
287         else if ((pFmt[nI] == '\'') && (!nI || pFmt[nI-1] != '\\'))
288             aBuffer[nI] = '\"';
289     }
290     rFmt = aBuffer.makeStringAndClear();
291 }
lcl_IsNotAM(OUString const & rFmt,sal_Int32 nPos)292 bool lcl_IsNotAM(OUString const & rFmt, sal_Int32 nPos)
293 {
294     return (
295             (nPos == rFmt.getLength() - 1) ||
296             (
297             (rFmt[nPos+1] != 'M') &&
298             (rFmt[nPos+1] != 'm')
299             )
300         );
301 }
302 }
303 
ConvertMSFormatStringToSO(const OUString & rFormat,lang::Locale & rLocale,bool bHijri)304 OUString ConvertMSFormatStringToSO(
305         const OUString& rFormat, lang::Locale& rLocale, bool bHijri)
306 {
307     OUString sFormat(rFormat);
308     lcl_SwapQuotesInField(sFormat);
309 
310     //#102782#, #102815#, #108341# & #111944# have to work at the same time :-)
311     bool bForceJapanese(false);
312     bool bForceNatNum(false);
313     sal_Int32 nLen = sFormat.getLength();
314     sal_Int32 nI = 0;
315 //    const sal_Unicode* pFormat = sFormat.getStr();
316     OUStringBuffer aNewFormat( sFormat );
317     while (nI < nLen)
318     {
319         if (aNewFormat[nI] == '\\')
320             nI++;
321         else if (aNewFormat[nI] == '\"')
322         {
323             ++nI;
324             //While not at the end and not at an unescaped end quote
325             while ((nI < nLen) && ((aNewFormat[nI] != '\"') && (aNewFormat[nI-1] != '\\')))
326                 ++nI;
327         }
328         else //normal unquoted section
329         {
330             sal_Unicode nChar = aNewFormat[nI];
331             if (nChar == 'O')
332             {
333                 aNewFormat[nI] = 'M';
334                 bForceNatNum = true;
335             }
336             else if (nChar == 'o')
337             {
338                 aNewFormat[nI] = 'm';
339                 bForceNatNum = true;
340             }
341             else if ((nChar == 'A') && lcl_IsNotAM(sFormat, nI))
342             {
343                 aNewFormat[nI] = 'D';
344                 bForceNatNum = true;
345             }
346             else if ((nChar == 'g') || (nChar == 'G'))
347                 bForceJapanese = true;
348             else if ((nChar == 'a') && lcl_IsNotAM(sFormat, nI))
349                 bForceJapanese = true;
350             else if (nChar == 'E')
351             {
352                 if ((nI != nLen-1) && (aNewFormat[nI+1] == 'E'))
353                 {
354                     //todo: this cannot be the right way to replace a part of the string!
355                     aNewFormat[nI] = 'Y';
356                     aNewFormat[nI + 1] = 'Y';
357                     aNewFormat.insert(nI + 2, "YY");
358                     nLen+=2;
359                     nI+=3;
360                 }
361                 bForceJapanese = true;
362             }
363             else if (nChar == 'e')
364             {
365                 if ((nI != nLen-1) && (aNewFormat[nI+1] == 'e'))
366                 {
367                     //todo: this cannot be the right way to replace a part of the string!
368                     aNewFormat[nI] = 'y';
369                     aNewFormat[nI + 1] = 'y';
370                     aNewFormat.insert(nI + 2, "yy");
371                     nLen+=2;
372                     nI+=3;
373                 }
374                 bForceJapanese = true;
375             }
376             else if (nChar == '/')
377             {
378                 // MM We have to escape '/' in case it's used as a char
379                 //todo: this cannot be the right way to replace a part of the string!
380                 aNewFormat[nI] = '\\';
381                 aNewFormat.insert(nI + 1, "/");
382                 nI++;
383                 nLen++;
384             }
385         }
386         ++nI;
387     }
388 
389     if (bForceNatNum)
390         bForceJapanese = true;
391 
392     if (bForceJapanese)
393     {
394         rLocale.Language = "ja";
395         rLocale.Country = "JP";
396     }
397 
398     if (bForceNatNum)
399     {
400         aNewFormat.insert( 0, "[NatNum1][$-411]");
401     }
402 
403     if (bHijri)
404     {
405         aNewFormat.insert( 0, "[~hijri]");
406     }
407     return aNewFormat.makeStringAndClear();
408 
409 }
410 
convertTwipToMM100(sal_Int32 _t)411 sal_Int32 convertTwipToMM100(sal_Int32 _t)
412 {
413     // It appears that MSO handles large twip values specially, probably legacy 16bit handling,
414     // anything that's bigger than 32767 appears to be simply ignored.
415     if( _t >= 0x8000 )
416         return 0;
417     return ::convertTwipToMm100( _t );
418 }
419 
convertTwipToMM100Unsigned(sal_Int32 _t)420 sal_uInt32 convertTwipToMM100Unsigned(sal_Int32 _t)
421 {
422     if( _t < 0 )
423         return 0;
424     return convertTwipToMM100( _t );
425 }
426 
convertRubyAlign(sal_Int32 nIntValue)427 text::RubyAdjust convertRubyAlign( sal_Int32 nIntValue )
428 {
429     text::RubyAdjust rubyAdjust = text::RubyAdjust_LEFT;
430     switch( nIntValue )
431     {
432         case NS_ooxml::LN_Value_ST_RubyAlign_center:
433         case NS_ooxml::LN_Value_ST_RubyAlign_rightVertical:
434             rubyAdjust = text::RubyAdjust_CENTER;
435             break;
436         case NS_ooxml::LN_Value_ST_RubyAlign_distributeLetter:
437             rubyAdjust = text::RubyAdjust_BLOCK;
438             break;
439         case NS_ooxml::LN_Value_ST_RubyAlign_distributeSpace:
440             rubyAdjust = text::RubyAdjust_INDENT_BLOCK;
441             break;
442         case NS_ooxml::LN_Value_ST_RubyAlign_left:
443             rubyAdjust = text::RubyAdjust_LEFT;
444             break;
445         case NS_ooxml::LN_Value_ST_RubyAlign_right:
446             rubyAdjust = text::RubyAdjust_RIGHT;
447             break;
448     }
449     return rubyAdjust;
450 }
451 
convertTableJustification(sal_Int32 nIntValue)452 sal_Int16 convertTableJustification( sal_Int32 nIntValue )
453 {
454     sal_Int16 nOrient = text::HoriOrientation::LEFT_AND_WIDTH;
455     switch( nIntValue )
456     {
457         case NS_ooxml::LN_Value_ST_Jc_center:
458             nOrient = text::HoriOrientation::CENTER;
459             break;
460         case NS_ooxml::LN_Value_ST_Jc_right:
461         case NS_ooxml::LN_Value_ST_Jc_end:
462             nOrient = text::HoriOrientation::RIGHT;
463             break;
464         case NS_ooxml::LN_Value_ST_Jc_left:
465         case NS_ooxml::LN_Value_ST_Jc_start:
466         //no break
467         default:;
468 
469     }
470     return nOrient;
471 }
472 
ConvertNumberingType(sal_Int32 nFmt)473 sal_Int16 ConvertNumberingType(sal_Int32 nFmt)
474 {
475     sal_Int16 nRet;
476     switch(nFmt)
477     {
478         case NS_ooxml::LN_Value_ST_NumberFormat_decimal:
479             nRet = style::NumberingType::ARABIC;
480             break;
481         case NS_ooxml::LN_Value_ST_NumberFormat_upperRoman:
482             nRet = style::NumberingType::ROMAN_UPPER;
483             break;
484         case NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman:
485             nRet = style::NumberingType::ROMAN_LOWER;
486             break;
487         case NS_ooxml::LN_Value_ST_NumberFormat_ordinal:
488             nRet = style::NumberingType::TEXT_NUMBER;
489             break;
490         case NS_ooxml::LN_Value_ST_NumberFormat_bullet:
491             nRet = style::NumberingType::CHAR_SPECIAL;
492         break;
493         case NS_ooxml::LN_Value_ST_NumberFormat_none:
494             nRet = style::NumberingType::NUMBER_NONE;
495             break;
496         case NS_ooxml::LN_Value_ST_NumberFormat_upperLetter:
497             nRet = style::NumberingType::CHARS_UPPER_LETTER_N;
498             break;
499         case  NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter:
500             nRet = style::NumberingType::CHARS_LOWER_LETTER_N;
501             break;
502         case NS_ooxml::LN_Value_ST_NumberFormat_iroha:
503             nRet = style::NumberingType::IROHA_HALFWIDTH_JA;
504             break;
505         case NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth:
506             nRet = style::NumberingType::IROHA_FULLWIDTH_JA;
507             break;
508         case NS_ooxml::LN_Value_ST_NumberFormat_aiueo:
509             nRet = style::NumberingType::AIU_HALFWIDTH_JA;
510             break;
511         case NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth:
512             nRet = style::NumberingType::AIU_FULLWIDTH_JA;
513             break;
514         case NS_ooxml::LN_Value_ST_NumberFormat_hebrew2:
515             nRet = style::NumberingType::CHARS_HEBREW;
516             break;
517         case NS_ooxml::LN_Value_ST_NumberFormat_thaiLetters:
518             nRet = style::NumberingType::CHARS_THAI;
519             break;
520         case NS_ooxml::LN_Value_ST_NumberFormat_russianLower:
521             nRet = style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU;
522             break;
523         case NS_ooxml::LN_Value_ST_NumberFormat_russianUpper:
524             nRet = style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU;
525             break;
526         case NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese:
527         case NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircle:
528         case NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle:
529             nRet = style::NumberingType::CIRCLE_NUMBER;
530             break;
531         case NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional:
532             nRet = style::NumberingType::TIAN_GAN_ZH;
533             break;
534         case NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac:
535             nRet = style::NumberingType::DI_ZI_ZH;
536             break;
537         case NS_ooxml::LN_Value_ST_NumberFormat_ganada:
538             nRet = style::NumberingType::HANGUL_SYLLABLE_KO;
539             break;
540         case NS_ooxml::LN_Value_ST_NumberFormat_chosung:
541             nRet = style::NumberingType::HANGUL_JAMO_KO;
542             break;
543         case NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal:
544         case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital:
545         case NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting:
546         case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2:
547             nRet = style::NumberingType::NUMBER_HANGUL_KO;
548             break;
549         case NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional:
550             nRet = style::NumberingType::NUMBER_UPPER_ZH_TW;
551             break;
552         case NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha:
553             nRet = style::NumberingType::CHARS_ARABIC;
554             break;
555         case NS_ooxml::LN_Value_ST_NumberFormat_hindiVowels:
556             nRet = style::NumberingType::CHARS_NEPALI;
557             break;
558         case NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal:
559             nRet = style::NumberingType::NUMBER_TRADITIONAL_JA;
560             break;
561         case NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting:
562         case NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting:
563         case NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting:
564         case NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand:
565         case NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital:
566         case NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand:
567             nRet = style::NumberingType::NUMBER_LOWER_ZH;
568             break;
569         case NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified:
570             nRet = style::NumberingType::NUMBER_UPPER_ZH;
571             break;
572         case NS_ooxml::LN_Value_ST_NumberFormat_hebrew1:
573             //91726
574             nRet = style::NumberingType::NUMBER_HEBREW;
575             break;
576         case NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth:
577         case NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2:
578             nRet = style::NumberingType::FULLWIDTH_ARABIC;
579             break;
580         case NS_ooxml::LN_Value_ST_NumberFormat_cardinalText:
581             nRet = style::NumberingType::TEXT_CARDINAL;
582             break;
583         case NS_ooxml::LN_Value_ST_NumberFormat_ordinalText:
584             nRet = style::NumberingType::TEXT_ORDINAL;
585             break;
586         case NS_ooxml::LN_Value_ST_NumberFormat_chicago:
587             nRet = style::NumberingType::SYMBOL_CHICAGO;
588             break;
589         default: nRet = style::NumberingType::ARABIC;
590     }
591 /*  TODO: Lots of additional values are available - some are supported in the I18 framework
592     NS_ooxml::LN_Value_ST_NumberFormat_hex = 91685;
593     NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth = 91691;
594     NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth = 91692;
595     NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand = 91694;
596     NS_ooxml::LN_Value_ST_NumberFormat_decimalZero = 91699;
597     NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop = 91703;
598     NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen = 91704;
599     NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional = 91709;
600     NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital = 91713;
601     NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified = 91715;
602     NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand = 91716;
603     NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal = 91719;
604     NS_ooxml::LN_Value_ST_NumberFormat_vietnameseCounting = 91721;
605     NS_ooxml::LN_Value_ST_NumberFormat_numberInDash = 91725;
606     NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad:
607     NS_ooxml::LN_Value_ST_NumberFormat_hindiConsonants = 91731;
608     NS_ooxml::LN_Value_ST_NumberFormat_hindiNumbers = 91732;
609     NS_ooxml::LN_Value_ST_NumberFormat_hindiCounting = 91733;
610     NS_ooxml::LN_Value_ST_NumberFormat_thaiNumbers = 91735;
611     NS_ooxml::LN_Value_ST_NumberFormat_thaiCounting = 91736;*/
612     return nRet;
613 }
614 
ConvertDateStringToDateTime(const OUString & rDateTime)615 util::DateTime ConvertDateStringToDateTime( const OUString& rDateTime )
616 {
617     util::DateTime aDateTime;
618     //xsd::DateTime in the format [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm] example: 2008-01-21T10:42:00Z
619     //OUString getToken( sal_Int32 token, sal_Unicode cTok, sal_Int32& index ) const
620     sal_Int32 nIndex = 0;
621     OUString sDate = rDateTime.getToken( 0, 'T', nIndex );
622     // HACK: this is broken according to the spec, but MSOffice always treats the time as local,
623     // and writes it as Z (=UTC+0)
624     OUString sTime = rDateTime.getToken( 0, 'Z', nIndex );
625     nIndex = 0;
626     aDateTime.Year = sal_uInt16( sDate.getToken( 0, '-', nIndex ).toInt32() );
627     aDateTime.Month = sal_uInt16( sDate.getToken( 0, '-', nIndex ).toInt32() );
628     if (nIndex != -1)
629         aDateTime.Day = sal_uInt16( sDate.copy( nIndex ).toInt32() );
630 
631     nIndex = 0;
632     aDateTime.Hours = sal_uInt16( sTime.getToken( 0, ':', nIndex ).toInt32() );
633     aDateTime.Minutes = sal_uInt16( sTime.getToken( 0, ':', nIndex ).toInt32() );
634     if (nIndex != -1)
635         aDateTime.Seconds = sal_uInt16( sTime.copy( nIndex ).toInt32() );
636 
637     return aDateTime;
638 }
639 
640 
641 } // namespace ConversionHelper
642 } //namespace dmapper
643 } //namespace writerfilter
644 
645 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
646