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 #include <ConversionHelper.hxx>
24 #include <com/sun/star/table/BorderLine.hpp>
25 #include <com/sun/star/lang/Locale.hpp>
26 #include <com/sun/star/text/HoriOrientation.hpp>
27 #include <com/sun/star/style/NumberingType.hpp>
28 #include <ooxml/resourceids.hxx>
29 #include <tools/color.hxx>
30 #include <rtl/ustrbuf.hxx>
31 #include <algorithm>
32 #include <functional>
33 
34 using namespace com::sun::star;
35 
36 namespace writerfilter {
37 namespace dmapper{
38 namespace ConversionHelper{
39 
40 #define TWIP_TO_MM100(TWIP)     ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L))
41 
42 //line definitions in 1/100 mm
43 #define LINE_WIDTH_0            2
44 #define LINE_WIDTH_1            36
45 #define LINE_WIDTH_2            89
46 #define LINE_WIDTH_3            142
47 #define LINE_WIDTH_4            177
48 #define LINE_WIDTH_5            18
49 
50 #define DOUBLE_LINE0_OUT    LINE_WIDTH_0
51 #define DOUBLE_LINE0_IN     LINE_WIDTH_0
52 #define DOUBLE_LINE0_DIST   LINE_WIDTH_1
53 
54 #define DOUBLE_LINE1_OUT    LINE_WIDTH_1
55 #define DOUBLE_LINE1_IN     LINE_WIDTH_1
56 #define DOUBLE_LINE1_DIST   LINE_WIDTH_1
57 
58 #define DOUBLE_LINE2_OUT    LINE_WIDTH_2
59 #define DOUBLE_LINE2_IN     LINE_WIDTH_2
60 #define DOUBLE_LINE2_DIST   LINE_WIDTH_2
61 
62 #define DOUBLE_LINE3_OUT    LINE_WIDTH_2
63 #define DOUBLE_LINE3_IN     LINE_WIDTH_1
64 #define DOUBLE_LINE3_DIST   LINE_WIDTH_2
65 
66 #define DOUBLE_LINE4_OUT    LINE_WIDTH_1
67 #define DOUBLE_LINE4_IN     LINE_WIDTH_2
68 #define DOUBLE_LINE4_DIST   LINE_WIDTH_1
69 
70 #define DOUBLE_LINE5_OUT    LINE_WIDTH_3
71 #define DOUBLE_LINE5_IN     LINE_WIDTH_2
72 #define DOUBLE_LINE5_DIST   LINE_WIDTH_2
73 
74 #define DOUBLE_LINE6_OUT    LINE_WIDTH_2
75 #define DOUBLE_LINE6_IN     LINE_WIDTH_3
76 #define DOUBLE_LINE6_DIST   LINE_WIDTH_2
77 
78 #define DOUBLE_LINE7_OUT    LINE_WIDTH_0
79 #define DOUBLE_LINE7_IN     LINE_WIDTH_0
80 #define DOUBLE_LINE7_DIST   LINE_WIDTH_2
81 
82 #define DOUBLE_LINE8_OUT    LINE_WIDTH_1
83 #define DOUBLE_LINE8_IN     LINE_WIDTH_0
84 #define DOUBLE_LINE8_DIST   LINE_WIDTH_2
85 
86 #define DOUBLE_LINE9_OUT    LINE_WIDTH_2
87 #define DOUBLE_LINE9_IN     LINE_WIDTH_0
88 #define DOUBLE_LINE9_DIST   LINE_WIDTH_2
89 
90 #define DOUBLE_LINE10_OUT   LINE_WIDTH_3
91 #define DOUBLE_LINE10_IN    LINE_WIDTH_0
92 #define DOUBLE_LINE10_DIST  LINE_WIDTH_2
93 
MakeBorderLine(sal_Int32 nSprmValue,table::BorderLine & rToFill)94 sal_Int32 MakeBorderLine( sal_Int32 nSprmValue, table::BorderLine& rToFill )
95 {
96     //TODO: Lines are always solid
97     //Border
98     //borders are defined as:
99     // 0x XX XX XX XX
100     //    || || || ||
101     //    || || ||  ---- Line width in 1/8 pt
102     //    || || ||
103     //    || ||  ------- Line type: 0 - none 1 - single ... 25 - engrave 3D and 64 - 230 page borders
104     //    || ||
105     //    ||  ---------- Line color
106     //    ||
107     //     ------------- seven bits line space
108     //    -------------- first bit: with shading
109     sal_Int16 nLineThicknessTwip = (sal_Int16)((nSprmValue & 0xff) * 20)/8L ;
110     sal_Int32 nLineType       = ((nSprmValue & 0xff00) >> 8);
111     sal_Int32 nLineColor    = (nSprmValue & 0xff0000)>>16;
112     sal_Int32 nLineDistance = (((nSprmValue & 0x3f000000)>>24) * 2540 + 36)/72L;
113     sal_Int32 nLineThickness = TWIP_TO_MM100(nLineThicknessTwip);
114     MakeBorderLine( nLineThickness, nLineType, nLineColor, rToFill, false);
115     return nLineDistance;
116 }
MakeBorderLine(sal_Int32 nLineThickness,sal_Int32 nLineType,sal_Int32 nLineColor,table::BorderLine & rToFill,bool bIsOOXML)117 void MakeBorderLine( sal_Int32 nLineThickness,   sal_Int32 nLineType,
118                                             sal_Int32 nLineColor,
119                                             table::BorderLine& rToFill, bool bIsOOXML )
120 {
121     static const sal_Int32 aBorderDefColor[] =
122     {
123         static_cast<sal_Int32>(COL_AUTO),
124         COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
125         COL_LIGHTMAGENTA, COL_LIGHTRED, COL_YELLOW, COL_WHITE, COL_BLUE,
126         COL_CYAN, COL_GREEN, COL_MAGENTA, COL_RED, COL_BROWN, COL_GRAY,
127         COL_LIGHTGRAY
128     };
129     //no auto color for borders
130     if(!nLineColor)
131         ++nLineColor;
132     if(!bIsOOXML && sal::static_int_cast<sal_uInt32>(nLineColor) <
133        sizeof(aBorderDefColor) / sizeof(nLineColor))
134         nLineColor = aBorderDefColor[nLineColor];
135 
136     enum eBorderCode
137     {
138         single0, single1, single2, single3, single4, single5,
139         double0, double1, double2, double3, double4, double5, double6,
140         double7, double8, double9, double10,
141         none
142     } eCodeIdx = none;
143 
144     // Map to our border types, we should use of one equal line
145     // thickness, or one of smaller thickness. If too small we
146     // can make the defecit up in additional white space or
147     // object size
148     switch(nLineType)
149     {
150         // First the single lines
151         case  1: break;
152         case  2:
153         case  5:
154         // and the unsupported special cases which we map to a single line
155         case  6:
156         case  7:
157         case  8:
158         case  9:
159         case 22:
160         // or if in necessary by a double line
161         case 24:
162         case 25:
163             if( nLineThickness < 10)
164                 eCodeIdx = single0;//   1 Twip for us
165             else if( nLineThickness < 20)
166                 eCodeIdx = single5;//   10 Twips for us
167             else if (nLineThickness < 50)
168                 eCodeIdx = single1;//  20 Twips
169             else if (nLineThickness < 80)
170                 eCodeIdx = single2;//  50
171             else if (nLineThickness < 100)
172                 eCodeIdx = single3;//  80
173             else if (nLineThickness < 150)
174                 eCodeIdx = single4;// 100
175             // Hack: for the quite thick lines we must paint double lines,
176             // because our singles lines don't come thicker than 5 points.
177             else if (nLineThickness < 180)
178                 eCodeIdx = double2;// 150
179             else
180                 eCodeIdx = double5;// 180
181         break;
182         // then the shading beams which we represent by a double line
183         case 23:
184             eCodeIdx = double1;
185         break;
186         // then the double lines, for which we have good matches
187         case  3:
188         case 10: //Don't have tripple so use double
189             if (nLineThickness < 60)
190                 eCodeIdx = double0;// 22 Twips for us
191             else if (nLineThickness < 135)
192                 eCodeIdx = double7;// some more space
193             else if (nLineThickness < 180)
194                 eCodeIdx = double1;// 60
195             else
196                 eCodeIdx = double2;// 150
197             break;
198         case 11:
199             eCodeIdx = double4;//  90 Twips for us
200             break;
201         case 12:
202         case 13: //Don't have thin thick thin, so use thick thin
203             if (nLineThickness < 87)
204                 eCodeIdx = double8;//  71 Twips for us
205             else if (nLineThickness < 117)
206                 eCodeIdx = double9;// 101
207             else if (nLineThickness < 166)
208                 eCodeIdx = double10;// 131
209             else
210                 eCodeIdx = double5;// 180
211             break;
212         case 14:
213             if (nLineThickness < 46)
214                 eCodeIdx = double0;//  22 Twips for us
215             else if (nLineThickness < 76)
216                 eCodeIdx = double1;//  60
217             else if (nLineThickness < 121)
218                 eCodeIdx = double4;//  90
219             else if (nLineThickness < 166)
220                 eCodeIdx = double2;// 150
221             else
222                 eCodeIdx = double6;// 180
223             break;
224         case 15:
225         case 16: //Don't have thin thick thin, so use thick thin
226             if (nLineThickness < 46)
227                 eCodeIdx = double0;//  22 Twips for us
228             else if (nLineThickness < 76)
229                 eCodeIdx = double1;//  60
230             else if (nLineThickness < 121)
231                 eCodeIdx = double3;//  90
232             else if (nLineThickness < 166)
233                 eCodeIdx = double2;// 150
234             else
235                 eCodeIdx = double5;// 180
236             break;
237         case 17:
238             if (nLineThickness < 46)
239                 eCodeIdx = double0;//  22 Twips for us
240             else if (nLineThickness < 72)
241                 eCodeIdx = double7;//  52
242             else if (nLineThickness < 137)
243                 eCodeIdx = double4;//  90
244             else
245                 eCodeIdx = double6;// 180
246         break;
247         case 18:
248         case 19: //Don't have thin thick thin, so use thick thin
249             if (nLineThickness < 46)
250                 eCodeIdx = double0;//  22 Twips for us
251             else if (nLineThickness < 62)
252                 eCodeIdx = double7;//  52
253             else if (nLineThickness < 87)
254                 eCodeIdx = double8;//  71
255             else if (nLineThickness < 117)
256                 eCodeIdx = double9;// 101
257             else if (nLineThickness < 156)
258                 eCodeIdx = double10;// 131
259             else
260                 eCodeIdx = double5;// 180
261             break;
262         case 20:
263             if (nLineThickness < 46)
264                 eCodeIdx = single1; //  20 Twips for us
265             else
266                 eCodeIdx = double1;//  60
267             break;
268         case 21:
269             eCodeIdx = double1;//  60 Twips for us
270             break;
271         case 0:
272         case 255:
273             eCodeIdx = none;
274             break;
275         default:
276             eCodeIdx = single0;
277             break;
278     }
279     struct BorderDefinition
280     {
281         sal_Int16 nOut;
282         sal_Int16 nIn;
283         sal_Int16 nDist;
284     };
285 
286 
287     static const BorderDefinition aLineTab[] =
288     {
289         /* 0*/  { LINE_WIDTH_0, 0, 0 },
290         /* 1*/  { LINE_WIDTH_1, 0, 0 },
291         /* 2*/  { LINE_WIDTH_2, 0, 0 },
292         /* 3*/  { LINE_WIDTH_3, 0, 0 },
293         /* 4*/  { LINE_WIDTH_4, 0, 0 },
294         /* 5*/  { LINE_WIDTH_5, 0, 0 },
295         /* 6*/  { DOUBLE_LINE0_OUT, DOUBLE_LINE0_IN, DOUBLE_LINE0_DIST },
296         /* 7*/  { DOUBLE_LINE1_OUT, DOUBLE_LINE1_IN, DOUBLE_LINE1_DIST },
297         /* 8*/  { DOUBLE_LINE2_OUT, DOUBLE_LINE2_IN, DOUBLE_LINE2_DIST },
298         /* 9*/  { DOUBLE_LINE3_OUT, DOUBLE_LINE3_IN, DOUBLE_LINE3_DIST },
299         /*10*/  { DOUBLE_LINE4_OUT, DOUBLE_LINE4_IN, DOUBLE_LINE4_DIST },
300         /*11*/  { DOUBLE_LINE5_OUT, DOUBLE_LINE5_IN, DOUBLE_LINE5_DIST },
301         /*12*/  { DOUBLE_LINE6_OUT, DOUBLE_LINE6_IN, DOUBLE_LINE6_DIST },
302         /*13*/  { DOUBLE_LINE7_OUT, DOUBLE_LINE7_IN, DOUBLE_LINE7_DIST },
303         /*14*/  { DOUBLE_LINE8_OUT, DOUBLE_LINE8_IN, DOUBLE_LINE8_DIST },
304         /*15*/  { DOUBLE_LINE9_OUT, DOUBLE_LINE9_IN, DOUBLE_LINE9_DIST },
305         /*16*/  { DOUBLE_LINE10_OUT,DOUBLE_LINE10_IN,DOUBLE_LINE10_DIST},
306         /*17*/  { 0, 0, 0 }
307     };
308 
309     rToFill.Color = nLineColor;
310     if( nLineType == 1)
311     {
312         rToFill.InnerLineWidth = 0;
313         rToFill.OuterLineWidth = sal_Int16(nLineThickness);
314         rToFill.LineDistance = 0;
315 
316     }
317     else
318     {
319         rToFill.InnerLineWidth = aLineTab[eCodeIdx].nIn;
320         rToFill.OuterLineWidth = aLineTab[eCodeIdx].nOut;
321         rToFill.LineDistance = aLineTab[eCodeIdx].nDist;
322     }
323 }
324 
lcl_SwapQuotesInField(::rtl::OUString & rFmt)325 void lcl_SwapQuotesInField(::rtl::OUString &rFmt)
326 {
327     //Swap unescaped " and ' with ' and "
328     sal_Int32 nLen = rFmt.getLength();
329     ::rtl::OUStringBuffer aBuffer( rFmt.getStr() );
330     const sal_Unicode* pFmt = rFmt.getStr();
331     for (sal_Int32 nI = 0; nI < nLen; ++nI)
332     {
333         if ((pFmt[nI] == '\"') && (!nI || pFmt[nI-1] != '\\'))
334             aBuffer.setCharAt(nI, '\'');
335         else if ((pFmt[nI] == '\'') && (!nI || pFmt[nI-1] != '\\'))
336             aBuffer.setCharAt(nI, '\"');
337     }
338     rFmt = aBuffer.makeStringAndClear();
339 }
lcl_IsNotAM(::rtl::OUString & rFmt,sal_Int32 nPos)340 bool lcl_IsNotAM(::rtl::OUString& rFmt, sal_Int32 nPos)
341 {
342     return (
343             (nPos == rFmt.getLength() - 1) ||
344             (
345             (rFmt.getStr()[nPos+1] != 'M') &&
346             (rFmt.getStr()[nPos+1] != 'm')
347             )
348         );
349 }
350 
ConvertMSFormatStringToSO(const::rtl::OUString & rFormat,lang::Locale & rLocale,bool bHijri)351 ::rtl::OUString ConvertMSFormatStringToSO(
352         const ::rtl::OUString& rFormat, lang::Locale& rLocale, bool bHijri)
353 {
354     ::rtl::OUString sFormat(rFormat);
355     lcl_SwapQuotesInField(sFormat);
356 
357     //#102782#, #102815#, #108341# & #111944# have to work at the same time :-)
358     bool bForceJapanese(false);
359     bool bForceNatNum(false);
360     sal_Int32 nLen = sFormat.getLength();
361     sal_Int32 nI = 0;
362 //    const sal_Unicode* pFormat = sFormat.getStr();
363     ::rtl::OUStringBuffer aNewFormat( sFormat.getStr() );
364     while (nI < nLen)
365     {
366         if (aNewFormat.charAt(nI) == '\\')
367             nI++;
368         else if (aNewFormat.charAt(nI) == '\"')
369         {
370             ++nI;
371             //While not at the end and not at an unescaped end quote
372             while ((nI < nLen) && (!(aNewFormat.charAt(nI) == '\"') && (aNewFormat.charAt(nI-1) != '\\')))
373                 ++nI;
374         }
375         else //normal unquoted section
376         {
377             sal_Unicode nChar = aNewFormat.charAt(nI);
378             if (nChar == 'O')
379             {
380                 aNewFormat.setCharAt(nI, 'M');
381                 bForceNatNum = true;
382             }
383             else if (nChar == 'o')
384             {
385                 aNewFormat.setCharAt(nI, 'm');
386                 bForceNatNum = true;
387             }
388             else if ((nChar == 'A') && lcl_IsNotAM(sFormat, nI))
389             {
390                 aNewFormat.setCharAt(nI, 'D');
391                 bForceNatNum = true;
392             }
393             else if ((nChar == 'g') || (nChar == 'G'))
394                 bForceJapanese = true;
395             else if ((nChar == 'a') && lcl_IsNotAM(sFormat, nI))
396                 bForceJapanese = true;
397             else if (nChar == 'E')
398             {
399                 if ((nI != nLen-1) && (aNewFormat.charAt(nI+1) == 'E'))
400                 {
401                     //todo: this cannot be the right way to replace a part of the string!
402                     aNewFormat.setCharAt( nI, 'Y' );
403                     aNewFormat.setCharAt( nI + 1, 'Y' );
404                     aNewFormat.insert(nI + 2, ::rtl::OUString::createFromAscii("YY"));
405                     nLen+=2;
406                     nI+=3;
407                 }
408                 bForceJapanese = true;
409             }
410             else if (nChar == 'e')
411             {
412                 if ((nI != nLen-1) && (aNewFormat.charAt(nI+1) == 'e'))
413                 {
414                     //todo: this cannot be the right way to replace a part of the string!
415                     aNewFormat.setCharAt( nI, 'y' );
416                     aNewFormat.setCharAt( nI + 1, 'y' );
417                     aNewFormat.insert(nI + 2, ::rtl::OUString::createFromAscii("yy"));
418                     nLen+=2;
419                     nI+=3;
420                 }
421                 bForceJapanese = true;
422             }
423             else if (nChar == '/')
424             {
425                 // MM We have to escape '/' in case it's used as a char
426                 //todo: this cannot be the right way to replace a part of the string!
427                 aNewFormat.setCharAt( nI, '\\' );
428                 aNewFormat.insert(nI + 1, ::rtl::OUString::createFromAscii("/"));
429                 nI++;
430                 nLen++;
431             }
432         }
433         ++nI;
434     }
435 
436     if (bForceNatNum)
437         bForceJapanese = true;
438 
439     if (bForceJapanese)
440     {
441         rLocale.Language =  ::rtl::OUString::createFromAscii("ja");
442         rLocale.Country = ::rtl::OUString::createFromAscii("JP");
443     }
444 
445     if (bForceNatNum)
446     {
447         aNewFormat.insert( 0, ::rtl::OUString::createFromAscii("[NatNum1][$-411]"));
448     }
449 
450     if (bHijri)
451     {
452         aNewFormat.insert( 0, ::rtl::OUString::createFromAscii("[~hijri]"));
453     }
454     return aNewFormat.makeStringAndClear();
455 
456 }
457 /*-------------------------------------------------------------------------
458 
459   -----------------------------------------------------------------------*/
convertTwipToMM100(sal_Int32 _t)460 sal_Int32 convertTwipToMM100(sal_Int32 _t)
461 {
462     return TWIP_TO_MM100( _t );
463 }
464 /*-- 09.08.2007 09:34:44---------------------------------------------------
465 
466   -----------------------------------------------------------------------*/
convertEMUToMM100(sal_Int32 _t)467 sal_Int32 convertEMUToMM100(sal_Int32 _t)
468 {
469     return _t / 360;
470 }
471 
472 /*-- 21.11.2006 08:47:12---------------------------------------------------
473     contains a color from 0xTTRRGGBB to 0xTTRRGGBB
474   -----------------------------------------------------------------------*/
ConvertColor(sal_Int32 nWordColor)475 sal_Int32 ConvertColor(sal_Int32 nWordColor)
476 {
477     sal_uInt8
478         r(static_cast<sal_uInt8>(nWordColor&0xFF)),
479         g(static_cast<sal_uInt8>(((nWordColor)>>8)&0xFF)),
480         b(static_cast<sal_uInt8>((nWordColor>>16)&0xFF)),
481         t(static_cast<sal_uInt8>((nWordColor>>24)&0xFF));
482     sal_Int32 nRet = (t<<24) + (r<<16) + (g<<8) + b;
483     return nRet;
484 }
485 /*-- 27.06.2007 13:42:32---------------------------------------------------
486 
487   -----------------------------------------------------------------------*/
convertTableJustification(sal_Int32 nIntValue)488 sal_Int16 convertTableJustification( sal_Int32 nIntValue )
489 {
490     sal_Int16 nOrient = text::HoriOrientation::LEFT_AND_WIDTH;
491     switch( nIntValue )
492     {
493         case 1 : nOrient = text::HoriOrientation::CENTER; break;
494         case 2 : nOrient = text::HoriOrientation::RIGHT; break;
495         case 0 :
496         //no break
497         default:;
498 
499     }
500     return nOrient;
501 }
502 /*-- 06.08.2007 15:27:30---------------------------------------------------
503      conversion form xsd::DateTime
504     [-]CCYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
505   -----------------------------------------------------------------------*/
convertDateTime(const::rtl::OUString & rDateTimeString)506 com::sun::star::util::DateTime convertDateTime( const ::rtl::OUString& rDateTimeString )
507 {
508     util::DateTime aRet( 0, 0, 0, 0, 1, 1, 1901 );
509     //
510     sal_Int32 nIndex = 0;
511     ::rtl::OUString sDate( rDateTimeString.getToken( 0, 'T', nIndex ));
512     sal_Int32 nDateIndex = 0;
513     aRet.Year = (sal_uInt16)sDate.getToken( 0, '-', nDateIndex ).toInt32();
514     if( nDateIndex > 0)
515         aRet.Month = (sal_uInt16)sDate.getToken( 0, '-', nDateIndex ).toInt32();
516     if( nDateIndex > 0)
517         aRet.Day = (sal_uInt16)sDate.getToken( 0, '-', nDateIndex ).toInt32();
518     ::rtl::OUString sTime;
519     if(nIndex > 0)
520     {
521         sTime = ( rDateTimeString.getToken( 0, 'Z', nIndex ));
522         sal_Int32 nTimeIndex = 0;
523         aRet.Hours = (sal_uInt16)sTime.getToken( 0, ':', nTimeIndex ).toInt32();
524         if( nTimeIndex > 0)
525             aRet.Minutes = (sal_uInt16)sTime.getToken( 0, ':', nTimeIndex ).toInt32();
526         if( nTimeIndex > 0)
527         {
528             ::rtl::OUString sSeconds = sTime.getToken( 0, ':', nTimeIndex );
529             nTimeIndex = 0;
530             aRet.Seconds = (sal_uInt16)sSeconds.getToken( 0, '.', nTimeIndex ).toInt32();
531             aRet.HundredthSeconds = (sal_uInt16)sSeconds.getToken( 0, '.', nTimeIndex ).toInt32();
532         }
533 
534 // todo: ignore time offset for a while - there's no time zone available
535 //        nIndex = 0;
536 //        ::rtl::OUString sOffset( rDateTimeString.getToken( 1, 'Z', nIndex ));
537 //        if( sOffset.getLength() )
538 //        {
539 //              add hour and minute offset and increase/decrease date if necessary
540 //        }
541     }
542     return aRet;
543 }
544 /*-- 05.03.2008 09:10:13---------------------------------------------------
545 
546   -----------------------------------------------------------------------*/
ConvertNumberingType(sal_Int32 nNFC)547 sal_Int16 ConvertNumberingType(sal_Int32 nNFC)
548 {
549     sal_Int16 nRet;
550     switch(nNFC)
551     {
552         case NS_ooxml::LN_Value_ST_NumberFormat_decimal:
553         case 0:
554             nRet = style::NumberingType::ARABIC;
555             break;
556         case NS_ooxml::LN_Value_ST_NumberFormat_upperRoman:
557         case 1:
558             nRet = style::NumberingType::ROMAN_UPPER;
559             break;
560         case NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman:
561         case 2:
562             nRet = style::NumberingType::ROMAN_LOWER;
563             break;
564         case NS_ooxml::LN_Value_ST_NumberFormat_ordinal:
565         case 3:
566             nRet = style::NumberingType::CHARS_UPPER_LETTER_N;
567             break;
568         case 4:
569             nRet = style::NumberingType::CHARS_LOWER_LETTER_N;
570             break;
571         case 5:
572             nRet = style::NumberingType::ARABIC;
573             break;//ORDINAL
574         case NS_ooxml::LN_Value_ST_NumberFormat_bullet:
575         case 23:
576         case 25:
577             nRet = style::NumberingType::CHAR_SPECIAL;
578         break;
579         case NS_ooxml::LN_Value_ST_NumberFormat_none:
580         case 255:
581             nRet = style::NumberingType::NUMBER_NONE;
582             break;
583         case NS_ooxml::LN_Value_ST_NumberFormat_upperLetter:
584             nRet = style::NumberingType::CHARS_UPPER_LETTER_N;
585             break;
586         case  NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter:
587             nRet = style::NumberingType::CHARS_LOWER_LETTER_N;
588             break;
589         case NS_ooxml::LN_Value_ST_NumberFormat_iroha:
590             nRet = style::NumberingType::IROHA_HALFWIDTH_JA;
591             break;
592         case NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth:
593             nRet = style::NumberingType::IROHA_FULLWIDTH_JA;
594             break;
595         case NS_ooxml::LN_Value_ST_NumberFormat_aiueo:
596             nRet = style::NumberingType::AIU_HALFWIDTH_JA;
597             break;
598         case NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth:
599             nRet = style::NumberingType::AIU_FULLWIDTH_JA;
600             break;
601         case NS_ooxml::LN_Value_ST_NumberFormat_hebrew2:
602             nRet = style::NumberingType::CHARS_HEBREW;
603             break;
604         case NS_ooxml::LN_Value_ST_NumberFormat_thaiLetters:
605             nRet = style::NumberingType::CHARS_THAI;
606             break;
607         case NS_ooxml::LN_Value_ST_NumberFormat_russianLower:
608             nRet = style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU;
609             break;
610         case NS_ooxml::LN_Value_ST_NumberFormat_russianUpper:
611             nRet = style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU;
612             break;
613         case NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese:
614         case NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle:
615             nRet = style::NumberingType::CIRCLE_NUMBER;
616             break;
617         case NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional:
618             nRet = style::NumberingType::TIAN_GAN_ZH;
619             break;
620         case NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac:
621             nRet = style::NumberingType::DI_ZI_ZH;
622             break;
623         case NS_ooxml::LN_Value_ST_NumberFormat_ganada:
624             nRet = style::NumberingType::HANGUL_SYLLABLE_KO;
625             break;
626         case NS_ooxml::LN_Value_ST_NumberFormat_chosung:
627             nRet = style::NumberingType::HANGUL_JAMO_KO;
628             break;
629         case NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal:
630         case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital:
631         case NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting:
632             nRet = style::NumberingType::NUMBER_HANGUL_KO;
633             break;
634         case NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional:
635             nRet = style::NumberingType::NUMBER_UPPER_ZH_TW;
636             break;
637         case NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha:
638             nRet = style::NumberingType::CHARS_ARABIC;
639             break;
640         case NS_ooxml::LN_Value_ST_NumberFormat_hindiVowels:
641             nRet = style::NumberingType::CHARS_NEPALI;
642             break;
643         case NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal:
644             nRet = style::NumberingType::NUMBER_TRADITIONAL_JA;
645             break;
646         case NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting:
647         case NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting:
648         case NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting:
649         case NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand:
650         case NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital:
651         case NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand:
652         case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2:
653             nRet = style::NumberingType::NUMBER_LOWER_ZH;
654             break;
655         case NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified:
656             nRet = style::NumberingType::NUMBER_UPPER_ZH;
657             break;
658         case NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth:
659         case NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2:
660             nRet = style::NumberingType::FULLWIDTH_ARABIC;
661             break;
662         default: nRet = style::NumberingType::ARABIC;
663     }
664 /*  TODO: Lots of additional values are available - some are supported in the I18 framework
665     NS_ooxml::LN_Value_ST_NumberFormat_ordinal = 91682;
666     NS_ooxml::LN_Value_ST_NumberFormat_cardinalText = 91683;
667     NS_ooxml::LN_Value_ST_NumberFormat_ordinalText = 91684;
668     NS_ooxml::LN_Value_ST_NumberFormat_hex = 91685;
669     NS_ooxml::LN_Value_ST_NumberFormat_chicago = 91686;
670     NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth = 91691;
671     NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth = 91692;
672     NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand = 91694;
673     NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircle = 91695;
674     NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2 = 91696;
675     NS_ooxml::LN_Value_ST_NumberFormat_decimalZero = 91699;
676     NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop = 91703;
677     NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen = 91704;
678     NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional = 91709;
679     NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand = 91712;
680     NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital = 91713;
681     NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified = 91715;
682     NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand = 91716;
683     NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal = 91719;
684     NS_ooxml::LN_Value_ST_NumberFormat_vietnameseCounting = 91721;
685     NS_ooxml::LN_Value_ST_NumberFormat_numberInDash = 91725;
686     NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad:
687     NS_ooxml::LN_Value_ST_NumberFormat_hebrew1 = 91726;
688     NS_ooxml::LN_Value_ST_NumberFormat_hindiConsonants = 91731;
689     NS_ooxml::LN_Value_ST_NumberFormat_hindiNumbers = 91732;
690     NS_ooxml::LN_Value_ST_NumberFormat_hindiCounting = 91733;
691     NS_ooxml::LN_Value_ST_NumberFormat_thaiNumbers = 91735;
692     NS_ooxml::LN_Value_ST_NumberFormat_thaiCounting = 91736;*/
693     return nRet;
694 }
695 
696 
697 } // namespace ConversionHelper
698 } //namespace dmapper
699 } //namespace writerfilter
700