PageRenderTime 64ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/libreoffice-3.6.0.2/svl/source/numbers/zforscan.cxx

#
C++ | 2747 lines | 2525 code | 69 blank | 153 comment | 630 complexity | 55af38704f2ae0ab1cbc4f5fc13bc5fc MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, AGPL-1.0, BSD-3-Clause-No-Nuclear-License-2014, GPL-3.0, LGPL-3.0
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*************************************************************************
  3. *
  4. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5. *
  6. * Copyright 2000, 2010 Oracle and/or its affiliates.
  7. *
  8. * OpenOffice.org - a multi-platform office productivity suite
  9. *
  10. * This file is part of OpenOffice.org.
  11. *
  12. * OpenOffice.org is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Lesser General Public License version 3
  14. * only, as published by the Free Software Foundation.
  15. *
  16. * OpenOffice.org is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU Lesser General Public License version 3 for more details
  20. * (a copy is included in the LICENSE file that accompanied this code).
  21. *
  22. * You should have received a copy of the GNU Lesser General Public License
  23. * version 3 along with OpenOffice.org. If not, see
  24. * <http://www.openoffice.org/license.html>
  25. * for a copy of the LGPLv3 License.
  26. *
  27. ************************************************************************/
  28. #include <stdlib.h>
  29. #include <tools/debug.hxx>
  30. #include <i18npool/mslangid.hxx>
  31. #include <unotools/charclass.hxx>
  32. #include <unotools/localedatawrapper.hxx>
  33. #include <unotools/numberformatcodewrapper.hxx>
  34. #include <rtl/instance.hxx>
  35. #include <svl/zforlist.hxx>
  36. #include <svl/zformat.hxx>
  37. #include <unotools/digitgroupingiterator.hxx>
  38. #define _ZFORSCAN_CXX
  39. #include "zforscan.hxx"
  40. #undef _ZFORSCAN_CXX
  41. #include <svl/nfsymbol.hxx>
  42. using namespace svt;
  43. const sal_Unicode cNonBreakingSpace = 0xA0;
  44. namespace
  45. {
  46. struct ImplEnglishColors
  47. {
  48. const String* operator()()
  49. {
  50. static const String aEnglishColors[NF_MAX_DEFAULT_COLORS] =
  51. {
  52. String( RTL_CONSTASCII_USTRINGPARAM( "BLACK" ) ),
  53. String( RTL_CONSTASCII_USTRINGPARAM( "BLUE" ) ),
  54. String( RTL_CONSTASCII_USTRINGPARAM( "GREEN" ) ),
  55. String( RTL_CONSTASCII_USTRINGPARAM( "CYAN" ) ),
  56. String( RTL_CONSTASCII_USTRINGPARAM( "RED" ) ),
  57. String( RTL_CONSTASCII_USTRINGPARAM( "MAGENTA" ) ),
  58. String( RTL_CONSTASCII_USTRINGPARAM( "BROWN" ) ),
  59. String( RTL_CONSTASCII_USTRINGPARAM( "GREY" ) ),
  60. String( RTL_CONSTASCII_USTRINGPARAM( "YELLOW" ) ),
  61. String( RTL_CONSTASCII_USTRINGPARAM( "WHITE" ) )
  62. };
  63. return &aEnglishColors[0];
  64. }
  65. };
  66. struct theEnglishColors
  67. : public rtl::StaticAggregate< const String, ImplEnglishColors> {};
  68. }
  69. ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP )
  70. {
  71. pFormatter = pFormatterP;
  72. bConvertMode = false;
  73. //! All keywords MUST be UPPERCASE!
  74. sKeyword[NF_KEY_E].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "E" ) ); // Exponent
  75. sKeyword[NF_KEY_AMPM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AM/PM" ) ); // AM/PM
  76. sKeyword[NF_KEY_AP].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "A/P" ) ); // AM/PM short
  77. sKeyword[NF_KEY_MI].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); // Minute
  78. sKeyword[NF_KEY_MMI].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); // Minute 02
  79. sKeyword[NF_KEY_S].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "S" ) ); // Second
  80. sKeyword[NF_KEY_SS].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "SS" ) ); // Second 02
  81. sKeyword[NF_KEY_Q].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Q" ) ); // Quarter short 'Q'
  82. sKeyword[NF_KEY_QQ].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "QQ" ) ); // Quarter long
  83. sKeyword[NF_KEY_NN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NN" ) ); // Day of week short
  84. sKeyword[NF_KEY_NNN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NNN" ) ); // Day of week long
  85. sKeyword[NF_KEY_NNNN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NNNN" ) ); // Day of week long incl. separator
  86. sKeyword[NF_KEY_WW].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WW" ) ); // Week of year
  87. sKeyword[NF_KEY_CCC].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CCC" ) ); // Currency abbreviation
  88. bKeywordsNeedInit = true; // locale dependent keywords
  89. bCompatCurNeedInit = true; // locale dependent compatibility currency strings
  90. StandardColor[0] = Color(COL_BLACK);
  91. StandardColor[1] = Color(COL_LIGHTBLUE);
  92. StandardColor[2] = Color(COL_LIGHTGREEN);
  93. StandardColor[3] = Color(COL_LIGHTCYAN);
  94. StandardColor[4] = Color(COL_LIGHTRED);
  95. StandardColor[5] = Color(COL_LIGHTMAGENTA);
  96. StandardColor[6] = Color(COL_BROWN);
  97. StandardColor[7] = Color(COL_GRAY);
  98. StandardColor[8] = Color(COL_YELLOW);
  99. StandardColor[9] = Color(COL_WHITE);
  100. pNullDate = new Date(30,12,1899);
  101. nStandardPrec = 2;
  102. sErrStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###" ) );
  103. Reset();
  104. }
  105. ImpSvNumberformatScan::~ImpSvNumberformatScan()
  106. {
  107. delete pNullDate;
  108. Reset();
  109. }
  110. void ImpSvNumberformatScan::ChangeIntl()
  111. {
  112. bKeywordsNeedInit = true;
  113. bCompatCurNeedInit = true;
  114. // may be initialized by InitSpecialKeyword()
  115. sKeyword[NF_KEY_TRUE].Erase();
  116. sKeyword[NF_KEY_FALSE].Erase();
  117. }
  118. void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const
  119. {
  120. switch ( eIdx )
  121. {
  122. case NF_KEY_TRUE :
  123. ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] =
  124. pFormatter->GetCharClass()->uppercase(
  125. pFormatter->GetLocaleData()->getTrueWord() );
  126. if ( !sKeyword[NF_KEY_TRUE].Len() )
  127. {
  128. SAL_WARN( "svl.numbers", "InitSpecialKeyword: TRUE_WORD?" );
  129. ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TRUE" ) );
  130. }
  131. break;
  132. case NF_KEY_FALSE :
  133. ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] =
  134. pFormatter->GetCharClass()->uppercase(
  135. pFormatter->GetLocaleData()->getFalseWord() );
  136. if ( !sKeyword[NF_KEY_FALSE].Len() )
  137. {
  138. SAL_WARN( "svl.numbers", "InitSpecialKeyword: FALSE_WORD?" );
  139. ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "FALSE" ) );
  140. }
  141. break;
  142. default:
  143. SAL_WARN( "svl.numbers", "InitSpecialKeyword: unknown request" );
  144. }
  145. }
  146. void ImpSvNumberformatScan::InitCompatCur() const
  147. {
  148. ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this;
  149. // currency symbol for old style ("automatic") compatibility format codes
  150. pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev );
  151. // currency symbol upper case
  152. pThis->sCurString = pFormatter->GetCharClass()->uppercase( sCurSymbol );
  153. bCompatCurNeedInit = false;
  154. }
  155. void ImpSvNumberformatScan::InitKeywords() const
  156. {
  157. if ( !bKeywordsNeedInit )
  158. return ;
  159. ((ImpSvNumberformatScan*)this)->SetDependentKeywords();
  160. bKeywordsNeedInit = false;
  161. }
  162. /** Extract the name of General, Standard, Whatever, ignoring leading modifiers
  163. such as [NatNum1]. */
  164. static String lcl_extractStandardGeneralName( const ::rtl::OUString & rCode )
  165. {
  166. String aStr;
  167. const sal_Unicode* p = rCode.getStr();
  168. const sal_Unicode* const pStop = p + rCode.getLength();
  169. const sal_Unicode* pBeg = p; // name begins here
  170. bool bMod = false;
  171. bool bDone = false;
  172. while (p < pStop && !bDone)
  173. {
  174. switch (*p)
  175. {
  176. case '[':
  177. bMod = true;
  178. break;
  179. case ']':
  180. if (bMod)
  181. {
  182. bMod = false;
  183. pBeg = p+1;
  184. }
  185. // else: would be a locale data error, easily to be spotted in
  186. // UI dialog
  187. break;
  188. case ';':
  189. if (!bMod)
  190. {
  191. bDone = true;
  192. --p; // put back, increment by one follows
  193. }
  194. break;
  195. }
  196. ++p;
  197. if (bMod)
  198. pBeg = p;
  199. }
  200. if (pBeg < p)
  201. aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg);
  202. return aStr;
  203. }
  204. void ImpSvNumberformatScan::SetDependentKeywords()
  205. {
  206. using namespace ::com::sun::star;
  207. using namespace ::com::sun::star::uno;
  208. const CharClass* pCharClass = pFormatter->GetCharClass();
  209. const LocaleDataWrapper* pLocaleData = pFormatter->GetLocaleData();
  210. // #80023# be sure to generate keywords for the loaded Locale, not for the
  211. // requested Locale, otherwise number format codes might not match
  212. lang::Locale aLoadedLocale = pLocaleData->getLoadedLocale();
  213. LanguageType eLang = MsLangId::convertLocaleToLanguage( aLoadedLocale );
  214. NumberFormatCodeWrapper aNumberFormatCode( pFormatter->GetServiceManager(), aLoadedLocale );
  215. i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD );
  216. sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code);
  217. sKeyword[NF_KEY_GENERAL] = pCharClass->uppercase( sNameStandardFormat );
  218. // preset new calendar keywords
  219. sKeyword[NF_KEY_AAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAA" ) );
  220. sKeyword[NF_KEY_AAAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAAA" ) );
  221. sKeyword[NF_KEY_EC].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "E" ) );
  222. sKeyword[NF_KEY_EEC].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EE" ) );
  223. sKeyword[NF_KEY_G].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "G" ) );
  224. sKeyword[NF_KEY_GG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GG" ) );
  225. sKeyword[NF_KEY_GGG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGG" ) );
  226. sKeyword[NF_KEY_R].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "R" ) );
  227. sKeyword[NF_KEY_RR].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "RR" ) );
  228. // Thai T NatNum special. Other locale's small letter 't' results in upper
  229. // case comparison not matching but length does in conversion mode. Ugly.
  230. if (eLang == LANGUAGE_THAI)
  231. sKeyword[NF_KEY_THAI_T].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T"));
  232. else
  233. sKeyword[NF_KEY_THAI_T].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "t"));
  234. switch ( eLang )
  235. {
  236. case LANGUAGE_GERMAN:
  237. case LANGUAGE_GERMAN_SWISS:
  238. case LANGUAGE_GERMAN_AUSTRIAN:
  239. case LANGUAGE_GERMAN_LUXEMBOURG:
  240. case LANGUAGE_GERMAN_LIECHTENSTEIN:
  241. {
  242. //! all capital letters
  243. sKeyword[NF_KEY_M].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); // month 1
  244. sKeyword[NF_KEY_MM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); // month 01
  245. sKeyword[NF_KEY_MMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMM" ) ); // month Jan
  246. sKeyword[NF_KEY_MMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMM" ) ); // month Januar
  247. sKeyword[NF_KEY_MMMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMMM" ) );// month J
  248. sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "H" ) ); // hour 2
  249. sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "HH" ) ); // hour 02
  250. sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T" ) );
  251. sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TT" ) );
  252. sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TTT" ) );
  253. sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TTTT" ) );
  254. sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) );
  255. sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) );
  256. sKeyword[NF_KEY_BOOLEAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "LOGISCH" ) );
  257. sKeyword[NF_KEY_COLOR].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "FARBE" ) );
  258. sKeyword[NF_KEY_BLACK].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "SCHWARZ" ) );
  259. sKeyword[NF_KEY_BLUE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLAU" ) );
  260. sKeyword[NF_KEY_GREEN] = UniString( "GR" "\xDC" "N", RTL_TEXTENCODING_ISO_8859_1 );
  261. sKeyword[NF_KEY_CYAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CYAN" ) );
  262. sKeyword[NF_KEY_RED].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "ROT" ) );
  263. sKeyword[NF_KEY_MAGENTA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MAGENTA" ) );
  264. sKeyword[NF_KEY_BROWN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BRAUN" ) );
  265. sKeyword[NF_KEY_GREY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GRAU" ) );
  266. sKeyword[NF_KEY_YELLOW].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GELB" ) );
  267. sKeyword[NF_KEY_WHITE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WEISS" ) );
  268. }
  269. break;
  270. default:
  271. {
  272. // day
  273. switch ( eLang )
  274. {
  275. case LANGUAGE_ITALIAN :
  276. case LANGUAGE_ITALIAN_SWISS :
  277. sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "G" ) );
  278. sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GG" ) );
  279. sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGG" ) );
  280. sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGGG" ) );
  281. // must exchange the era code, same as Xcl
  282. sKeyword[NF_KEY_G].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "X" ) );
  283. sKeyword[NF_KEY_GG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "XX" ) );
  284. sKeyword[NF_KEY_GGG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "XXX" ) );
  285. break;
  286. case LANGUAGE_FRENCH :
  287. case LANGUAGE_FRENCH_BELGIAN :
  288. case LANGUAGE_FRENCH_CANADIAN :
  289. case LANGUAGE_FRENCH_SWISS :
  290. case LANGUAGE_FRENCH_LUXEMBOURG :
  291. case LANGUAGE_FRENCH_MONACO :
  292. sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "J" ) );
  293. sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) );
  294. sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJ" ) );
  295. sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) );
  296. break;
  297. case LANGUAGE_FINNISH :
  298. sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "P" ) );
  299. sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PP" ) );
  300. sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PPP" ) );
  301. sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PPPP" ) );
  302. break;
  303. default:
  304. sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D" ) );
  305. sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DD" ) );
  306. sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDD" ) );
  307. sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDDD" ) );
  308. }
  309. // month
  310. switch ( eLang )
  311. {
  312. case LANGUAGE_FINNISH :
  313. sKeyword[NF_KEY_M].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "K" ) );
  314. sKeyword[NF_KEY_MM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KK" ) );
  315. sKeyword[NF_KEY_MMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKK" ) );
  316. sKeyword[NF_KEY_MMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKKK" ) );
  317. sKeyword[NF_KEY_MMMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKKKK" ) );
  318. break;
  319. default:
  320. sKeyword[NF_KEY_M].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) );
  321. sKeyword[NF_KEY_MM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) );
  322. sKeyword[NF_KEY_MMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMM" ) );
  323. sKeyword[NF_KEY_MMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMM" ) );
  324. sKeyword[NF_KEY_MMMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMMM" ) );
  325. }
  326. // year
  327. switch ( eLang )
  328. {
  329. case LANGUAGE_ITALIAN :
  330. case LANGUAGE_ITALIAN_SWISS :
  331. case LANGUAGE_FRENCH :
  332. case LANGUAGE_FRENCH_BELGIAN :
  333. case LANGUAGE_FRENCH_CANADIAN :
  334. case LANGUAGE_FRENCH_SWISS :
  335. case LANGUAGE_FRENCH_LUXEMBOURG :
  336. case LANGUAGE_FRENCH_MONACO :
  337. case LANGUAGE_PORTUGUESE :
  338. case LANGUAGE_PORTUGUESE_BRAZILIAN :
  339. case LANGUAGE_SPANISH_MODERN :
  340. case LANGUAGE_SPANISH_DATED :
  341. case LANGUAGE_SPANISH_MEXICAN :
  342. case LANGUAGE_SPANISH_GUATEMALA :
  343. case LANGUAGE_SPANISH_COSTARICA :
  344. case LANGUAGE_SPANISH_PANAMA :
  345. case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC :
  346. case LANGUAGE_SPANISH_VENEZUELA :
  347. case LANGUAGE_SPANISH_COLOMBIA :
  348. case LANGUAGE_SPANISH_PERU :
  349. case LANGUAGE_SPANISH_ARGENTINA :
  350. case LANGUAGE_SPANISH_ECUADOR :
  351. case LANGUAGE_SPANISH_CHILE :
  352. case LANGUAGE_SPANISH_URUGUAY :
  353. case LANGUAGE_SPANISH_PARAGUAY :
  354. case LANGUAGE_SPANISH_BOLIVIA :
  355. case LANGUAGE_SPANISH_EL_SALVADOR :
  356. case LANGUAGE_SPANISH_HONDURAS :
  357. case LANGUAGE_SPANISH_NICARAGUA :
  358. case LANGUAGE_SPANISH_PUERTO_RICO :
  359. sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AA" ) );
  360. sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAAA" ) );
  361. // must exchange the day of week name code, same as Xcl
  362. sKeyword[NF_KEY_AAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OOO" ) );
  363. sKeyword[NF_KEY_AAAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OOOO" ) );
  364. break;
  365. case LANGUAGE_DUTCH :
  366. case LANGUAGE_DUTCH_BELGIAN :
  367. sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) );
  368. sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) );
  369. break;
  370. case LANGUAGE_FINNISH :
  371. sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "VV" ) );
  372. sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "VVVV" ) );
  373. break;
  374. default:
  375. sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YY" ) );
  376. sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YYYY" ) );
  377. }
  378. // hour
  379. switch ( eLang )
  380. {
  381. case LANGUAGE_DUTCH :
  382. case LANGUAGE_DUTCH_BELGIAN :
  383. sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "U" ) );
  384. sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "UU" ) );
  385. break;
  386. case LANGUAGE_FINNISH :
  387. case LANGUAGE_SWEDISH :
  388. case LANGUAGE_SWEDISH_FINLAND :
  389. case LANGUAGE_DANISH :
  390. case LANGUAGE_NORWEGIAN :
  391. case LANGUAGE_NORWEGIAN_BOKMAL :
  392. case LANGUAGE_NORWEGIAN_NYNORSK :
  393. sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T" ) );
  394. sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TT" ) );
  395. break;
  396. default:
  397. sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "H" ) );
  398. sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "HH" ) );
  399. }
  400. // boolean
  401. sKeyword[NF_KEY_BOOLEAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BOOLEAN" ) );
  402. // colours
  403. sKeyword[NF_KEY_COLOR].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "COLOR" ) );
  404. sKeyword[NF_KEY_BLACK].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLACK" ) );
  405. sKeyword[NF_KEY_BLUE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLUE" ) );
  406. sKeyword[NF_KEY_GREEN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GREEN" ) );
  407. sKeyword[NF_KEY_CYAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CYAN" ) );
  408. sKeyword[NF_KEY_RED].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "RED" ) );
  409. sKeyword[NF_KEY_MAGENTA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MAGENTA" ) );
  410. sKeyword[NF_KEY_BROWN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BROWN" ) );
  411. sKeyword[NF_KEY_GREY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GREY" ) );
  412. sKeyword[NF_KEY_YELLOW].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YELLOW" ) );
  413. sKeyword[NF_KEY_WHITE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WHITE" ) );
  414. }
  415. break;
  416. }
  417. // boolean keyords
  418. InitSpecialKeyword( NF_KEY_TRUE );
  419. InitSpecialKeyword( NF_KEY_FALSE );
  420. // compatibility currency strings
  421. InitCompatCur();
  422. }
  423. void ImpSvNumberformatScan::ChangeNullDate(sal_uInt16 nDay, sal_uInt16 nMonth, sal_uInt16 nYear)
  424. {
  425. if ( pNullDate )
  426. *pNullDate = Date(nDay, nMonth, nYear);
  427. else
  428. pNullDate = new Date(nDay, nMonth, nYear);
  429. }
  430. void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec)
  431. {
  432. nStandardPrec = nPrec;
  433. }
  434. Color* ImpSvNumberformatScan::GetColor(String& sStr)
  435. {
  436. String sString = pFormatter->GetCharClass()->uppercase(sStr);
  437. const NfKeywordTable & rKeyword = GetKeywords();
  438. size_t i = 0;
  439. while (i < NF_MAX_DEFAULT_COLORS &&
  440. sString != rKeyword[NF_KEY_FIRSTCOLOR+i] )
  441. i++;
  442. if ( i >= NF_MAX_DEFAULT_COLORS )
  443. {
  444. const String* pEnglishColors = theEnglishColors::get();
  445. size_t j = 0;
  446. while ( j < NF_MAX_DEFAULT_COLORS &&
  447. sString != pEnglishColors[j] )
  448. ++j;
  449. if ( j < NF_MAX_DEFAULT_COLORS )
  450. i = j;
  451. }
  452. Color* pResult = NULL;
  453. if (i >= NF_MAX_DEFAULT_COLORS)
  454. {
  455. const String& rColorWord = rKeyword[NF_KEY_COLOR];
  456. xub_StrLen nPos = sString.Match(rColorWord);
  457. if (nPos > 0)
  458. {
  459. sStr.Erase(0, nPos);
  460. sStr.EraseLeadingChars();
  461. sStr.EraseTrailingChars();
  462. if (bConvertMode)
  463. {
  464. pFormatter->ChangeIntl(eNewLnge);
  465. sStr.Insert( GetKeywords()[NF_KEY_COLOR], 0 ); // Color -> FARBE
  466. pFormatter->ChangeIntl(eTmpLnge);
  467. }
  468. else
  469. sStr.Insert(rColorWord,0);
  470. sString.Erase(0, nPos);
  471. sString.EraseLeadingChars();
  472. sString.EraseTrailingChars();
  473. if ( CharClass::isAsciiNumeric( sString ) )
  474. {
  475. long nIndex = sString.ToInt32();
  476. if (nIndex > 0 && nIndex <= 64)
  477. pResult = pFormatter->GetUserDefColor((sal_uInt16)nIndex-1);
  478. }
  479. }
  480. }
  481. else
  482. {
  483. sStr.Erase();
  484. if (bConvertMode)
  485. {
  486. pFormatter->ChangeIntl(eNewLnge);
  487. sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i]; // red -> rot
  488. pFormatter->ChangeIntl(eTmpLnge);
  489. }
  490. else
  491. sStr = rKeyword[NF_KEY_FIRSTCOLOR+i];
  492. pResult = &(StandardColor[i]);
  493. }
  494. return pResult;
  495. }
  496. short ImpSvNumberformatScan::GetKeyWord( const String& sSymbol, xub_StrLen nPos )
  497. {
  498. String sString = pFormatter->GetCharClass()->uppercase( sSymbol, nPos, sSymbol.Len() - nPos );
  499. const NfKeywordTable & rKeyword = GetKeywords();
  500. // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere
  501. if ( sString.Search( rKeyword[NF_KEY_GENERAL] ) == 0 )
  502. return NF_KEY_GENERAL;
  503. //! MUST be a reverse search to find longer strings first
  504. short i = NF_KEYWORD_ENTRIES_COUNT-1;
  505. bool bFound = false;
  506. for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i )
  507. {
  508. bFound = sString.Search(rKeyword[i]) == 0;
  509. if ( bFound )
  510. {
  511. break;
  512. }
  513. }
  514. // new keywords take precedence over old keywords
  515. if ( !bFound )
  516. { // skip the gap of colors et al between new and old keywords and search on
  517. i = NF_KEY_LASTKEYWORD;
  518. while ( i > 0 && sString.Search(rKeyword[i]) != 0 )
  519. i--;
  520. if ( i > NF_KEY_LASTOLDKEYWORD && sString != rKeyword[i] )
  521. { // found something, but maybe it's something else?
  522. // e.g. new NNN is found in NNNN, for NNNN we must search on
  523. short j = i - 1;
  524. while ( j > 0 && sString.Search(rKeyword[j]) != 0 )
  525. j--;
  526. if ( j && rKeyword[j].Len() > rKeyword[i].Len() )
  527. return j;
  528. }
  529. }
  530. // The Thai T NatNum modifier during Xcl import.
  531. if (i == 0 && bConvertMode && sString.GetChar(0) == 'T' && eTmpLnge ==
  532. LANGUAGE_ENGLISH_US && MsLangId::getRealLanguage( eNewLnge) ==
  533. LANGUAGE_THAI)
  534. i = NF_KEY_THAI_T;
  535. return i; // 0 => not found
  536. }
  537. //---------------------------------------------------------------------------
  538. // Next_Symbol
  539. //---------------------------------------------------------------------------
  540. // Zerlegt die Eingabe in Symbole fuer die weitere
  541. // Verarbeitung (Turing-Maschine).
  542. //---------------------------------------------------------------------------
  543. // Ausgangs Zustand = SsStart
  544. //---------------+-------------------+-----------------------+---------------
  545. // Alter Zustand | gelesenes Zeichen | Aktion | Neuer Zustand
  546. //---------------+-------------------+-----------------------+---------------
  547. // SsStart | Buchstabe | Symbol=Zeichen | SsGetWord
  548. // | " | Typ = String | SsGetString
  549. // | \ | Typ = String | SsGetChar
  550. // | * | Typ = Star | SsGetStar
  551. // | _ | Typ = Blank | SsGetBlank
  552. // | @ # 0 ? / . , % [ | Symbol = Zeichen; |
  553. // | ] ' Blank | Typ = Steuerzeichen | SsStop
  554. // | $ - + ( ) : | Typ = String; |
  555. // | Sonst | Symbol = Zeichen | SsStop
  556. //---------------|-------------------+-----------------------+---------------
  557. // SsGetChar | Sonst | Symbol=Zeichen | SsStop
  558. //---------------+-------------------+-----------------------+---------------
  559. // GetString | " | | SsStop
  560. // | Sonst | Symbol+=Zeichen | GetString
  561. //---------------+-------------------+-----------------------+---------------
  562. // SsGetWord | Buchstabe | Symbol += Zeichen |
  563. // | + - (E+ E-)| Symbol += Zeichen | SsStop
  564. // | / (AM/PM)| Symbol += Zeichen |
  565. // | Sonst | Pos--, if Key Typ=Word| SsStop
  566. //---------------+-------------------+-----------------------+---------------
  567. // SsGetStar | Sonst | Symbol+=Zeichen | SsStop
  568. // | | markiere Sonderfall * |
  569. //---------------+-------------------+-----------------------+---------------
  570. // SsGetBlank | Sonst | Symbol+=Zeichen | SsStop
  571. // | | markiere Sonderfall _ |
  572. //---------------+-------------------+-----------------------+---------------
  573. // Wurde im State SsGetWord ein Schluesselwort erkannt (auch als
  574. // Anfangsteilwort des Symbols)
  575. // so werden die restlichen Buchstaben zurueckgeschrieben !!
  576. enum ScanState
  577. {
  578. SsStop = 0,
  579. SsStart = 1,
  580. SsGetChar = 2,
  581. SsGetString = 3,
  582. SsGetWord = 4,
  583. SsGetStar = 5,
  584. SsGetBlank = 6
  585. };
  586. short ImpSvNumberformatScan::Next_Symbol( const String& rStr,
  587. xub_StrLen& nPos, String& sSymbol )
  588. {
  589. if ( bKeywordsNeedInit )
  590. InitKeywords();
  591. const CharClass* pChrCls = pFormatter->GetCharClass();
  592. const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
  593. const xub_StrLen nStart = nPos;
  594. short eType = 0;
  595. ScanState eState = SsStart;
  596. sSymbol.Erase();
  597. while ( nPos < rStr.Len() && eState != SsStop )
  598. {
  599. sal_Unicode cToken = rStr.GetChar( nPos++ );
  600. switch (eState)
  601. {
  602. case SsStart:
  603. {
  604. // Fetch any currency longer than one character and don't get
  605. // confused later on by "E/" or other combinations of letters
  606. // and meaningful symbols. Necessary for old automatic currency.
  607. // #96158# But don't do it if we're starting a "[...]" section,
  608. // for example a "[$...]" new currency symbol to not parse away
  609. // "$U" (symbol) of "[$UYU]" (abbreviation).
  610. if ( nCurrPos != STRING_NOTFOUND && sCurString.Len() > 1 &&
  611. nPos-1 + sCurString.Len() <= rStr.Len() &&
  612. !(nPos > 1 && rStr.GetChar( nPos-2 ) == '[') )
  613. {
  614. String aTest = pChrCls->uppercase( rStr.Copy( nPos-1, sCurString.Len() ) );
  615. if ( aTest == sCurString )
  616. {
  617. sSymbol = rStr.Copy( --nPos, sCurString.Len() );
  618. nPos = nPos + sSymbol.Len();
  619. eState = SsStop;
  620. eType = NF_SYMBOLTYPE_STRING;
  621. return eType;
  622. }
  623. }
  624. switch (cToken)
  625. {
  626. case '#':
  627. case '0':
  628. case '?':
  629. case '%':
  630. case '@':
  631. case '[':
  632. case ']':
  633. case ',':
  634. case '.':
  635. case '/':
  636. case '\'':
  637. case ' ':
  638. case ':':
  639. case '-':
  640. {
  641. eType = NF_SYMBOLTYPE_DEL;
  642. sSymbol += cToken;
  643. eState = SsStop;
  644. }
  645. break;
  646. case '*':
  647. {
  648. eType = NF_SYMBOLTYPE_STAR;
  649. sSymbol += cToken;
  650. eState = SsGetStar;
  651. }
  652. break;
  653. case '_':
  654. {
  655. eType = NF_SYMBOLTYPE_BLANK;
  656. sSymbol += cToken;
  657. eState = SsGetBlank;
  658. }
  659. break;
  660. case '"':
  661. eType = NF_SYMBOLTYPE_STRING;
  662. eState = SsGetString;
  663. sSymbol += cToken;
  664. break;
  665. case '\\':
  666. eType = NF_SYMBOLTYPE_STRING;
  667. eState = SsGetChar;
  668. sSymbol += cToken;
  669. break;
  670. case '$':
  671. case '+':
  672. case '(':
  673. case ')':
  674. eType = NF_SYMBOLTYPE_STRING;
  675. eState = SsStop;
  676. sSymbol += cToken;
  677. break;
  678. default :
  679. {
  680. if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) ||
  681. StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) ||
  682. StringEqualsChar( pFormatter->GetDateSep(), cToken) ||
  683. StringEqualsChar( pLoc->getTimeSep(), cToken) ||
  684. StringEqualsChar( pLoc->getTime100SecSep(), cToken))
  685. {
  686. // Another separator than pre-known ASCII
  687. eType = NF_SYMBOLTYPE_DEL;
  688. sSymbol += cToken;
  689. eState = SsStop;
  690. }
  691. else if ( pChrCls->isLetter( rStr, nPos-1 ) )
  692. {
  693. short nTmpType = GetKeyWord( rStr, nPos-1 );
  694. if ( nTmpType )
  695. {
  696. bool bCurrency = false;
  697. // "Automatic" currency may start with keyword,
  698. // like "R" (Rand) and 'R' (era)
  699. if ( nCurrPos != STRING_NOTFOUND &&
  700. nPos-1 + sCurString.Len() <= rStr.Len() &&
  701. sCurString.Search( sKeyword[nTmpType] ) == 0 )
  702. {
  703. String aTest = pChrCls->uppercase( rStr.Copy( nPos-1, sCurString.Len() ) );
  704. if ( aTest == sCurString )
  705. bCurrency = true;
  706. }
  707. if ( bCurrency )
  708. {
  709. eState = SsGetWord;
  710. sSymbol += cToken;
  711. }
  712. else
  713. {
  714. eType = nTmpType;
  715. xub_StrLen nLen = sKeyword[eType].Len();
  716. sSymbol = rStr.Copy( nPos-1, nLen );
  717. if ( eType == NF_KEY_E || IsAmbiguousE( eType ) )
  718. {
  719. sal_Unicode cNext = rStr.GetChar(nPos);
  720. switch ( cNext )
  721. {
  722. case '+' :
  723. case '-' : // E+ E- combine to one symbol
  724. sSymbol += cNext;
  725. eType = NF_KEY_E;
  726. nPos++;
  727. break;
  728. case '0' :
  729. case '#' : // scientific E without sign
  730. eType = NF_KEY_E;
  731. break;
  732. }
  733. }
  734. nPos--;
  735. nPos = nPos + nLen;
  736. eState = SsStop;
  737. }
  738. }
  739. else
  740. {
  741. eState = SsGetWord;
  742. sSymbol += cToken;
  743. }
  744. }
  745. else
  746. {
  747. eType = NF_SYMBOLTYPE_STRING;
  748. eState = SsStop;
  749. sSymbol += cToken;
  750. }
  751. }
  752. break;
  753. }
  754. }
  755. break;
  756. case SsGetChar:
  757. {
  758. sSymbol += cToken;
  759. eState = SsStop;
  760. }
  761. break;
  762. case SsGetString:
  763. {
  764. if (cToken == '"')
  765. eState = SsStop;
  766. sSymbol += cToken;
  767. }
  768. break;
  769. case SsGetWord:
  770. {
  771. if ( pChrCls->isLetter( rStr, nPos-1 ) )
  772. {
  773. short nTmpType = GetKeyWord( rStr, nPos-1 );
  774. if ( nTmpType )
  775. { // beginning of keyword, stop scan and put back
  776. eType = NF_SYMBOLTYPE_STRING;
  777. eState = SsStop;
  778. nPos--;
  779. }
  780. else
  781. sSymbol += cToken;
  782. }
  783. else
  784. {
  785. bool bDontStop = false;
  786. switch (cToken)
  787. {
  788. case '/': // AM/PM, A/P
  789. {
  790. sal_Unicode cNext = rStr.GetChar(nPos);
  791. if ( cNext == 'P' || cNext == 'p' )
  792. {
  793. xub_StrLen nLen = sSymbol.Len();
  794. if ( 1 <= nLen
  795. && (sSymbol.GetChar(0) == 'A' || sSymbol.GetChar(0) == 'a')
  796. && (nLen == 1 || (nLen == 2
  797. && (sSymbol.GetChar(1) == 'M' || sSymbol.GetChar(1) == 'm')
  798. && (rStr.GetChar(nPos+1) == 'M' || rStr.GetChar(nPos+1) == 'm'))) )
  799. {
  800. sSymbol += cToken;
  801. bDontStop = true;
  802. }
  803. }
  804. }
  805. break;
  806. }
  807. // anything not recognized will stop the scan
  808. if ( eState != SsStop && !bDontStop )
  809. {
  810. eState = SsStop;
  811. nPos--;
  812. eType = NF_SYMBOLTYPE_STRING;
  813. }
  814. }
  815. }
  816. break;
  817. case SsGetStar:
  818. {
  819. eState = SsStop;
  820. sSymbol += cToken;
  821. nRepPos = (nPos - nStart) - 1; // everytime > 0!!
  822. }
  823. break;
  824. case SsGetBlank:
  825. {
  826. eState = SsStop;
  827. sSymbol += cToken;
  828. }
  829. break;
  830. default:
  831. break;
  832. } // of switch
  833. } // of while
  834. if (eState == SsGetWord)
  835. eType = NF_SYMBOLTYPE_STRING;
  836. return eType;
  837. }
  838. xub_StrLen ImpSvNumberformatScan::Symbol_Division(const String& rString)
  839. {
  840. nCurrPos = STRING_NOTFOUND;
  841. // Ist Waehrung im Spiel?
  842. String sString = pFormatter->GetCharClass()->uppercase(rString);
  843. xub_StrLen nCPos = 0;
  844. while (nCPos != STRING_NOTFOUND)
  845. {
  846. nCPos = sString.Search(GetCurString(),nCPos);
  847. if (nCPos != STRING_NOTFOUND)
  848. {
  849. // in Quotes?
  850. xub_StrLen nQ = SvNumberformat::GetQuoteEnd( sString, nCPos );
  851. if ( nQ == STRING_NOTFOUND )
  852. {
  853. sal_Unicode c;
  854. if ( nCPos == 0 ||
  855. ((c = sString.GetChar(xub_StrLen(nCPos-1))) != '"'
  856. && c != '\\') ) // dm kann durch "dm
  857. { // \d geschuetzt werden
  858. nCurrPos = nCPos;
  859. nCPos = STRING_NOTFOUND; // Abbruch
  860. }
  861. else
  862. nCPos++; // weitersuchen
  863. }
  864. else
  865. nCPos = nQ + 1; // weitersuchen
  866. }
  867. }
  868. nAnzStrings = 0;
  869. bool bStar = false; // wird bei '*'Detektion gesetzt
  870. Reset();
  871. xub_StrLen nPos = 0;
  872. const xub_StrLen nLen = rString.Len();
  873. while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS)
  874. {
  875. nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]);
  876. if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR)
  877. { // Ueberwachung des '*'
  878. if (bStar)
  879. return nPos; // Fehler: doppelter '*'
  880. else
  881. bStar = true;
  882. }
  883. nAnzStrings++;
  884. }
  885. return 0; // 0 => ok
  886. }
  887. void ImpSvNumberformatScan::SkipStrings(sal_uInt16& i, xub_StrLen& nPos)
  888. {
  889. while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING
  890. || nTypeArray[i] == NF_SYMBOLTYPE_BLANK
  891. || nTypeArray[i] == NF_SYMBOLTYPE_STAR) )
  892. {
  893. nPos = nPos + sStrArray[i].Len();
  894. i++;
  895. }
  896. }
  897. sal_uInt16 ImpSvNumberformatScan::PreviousKeyword(sal_uInt16 i)
  898. {
  899. short res = 0;
  900. if (i > 0 && i < nAnzStrings)
  901. {
  902. i--;
  903. while (i > 0 && nTypeArray[i] <= 0)
  904. i--;
  905. if (nTypeArray[i] > 0)
  906. res = nTypeArray[i];
  907. }
  908. return res;
  909. }
  910. sal_uInt16 ImpSvNumberformatScan::NextKeyword(sal_uInt16 i)
  911. {
  912. short res = 0;
  913. if (i < nAnzStrings-1)
  914. {
  915. i++;
  916. while (i < nAnzStrings-1 && nTypeArray[i] <= 0)
  917. i++;
  918. if (nTypeArray[i] > 0)
  919. res = nTypeArray[i];
  920. }
  921. return res;
  922. }
  923. short ImpSvNumberformatScan::PreviousType( sal_uInt16 i )
  924. {
  925. if ( i > 0 && i < nAnzStrings )
  926. {
  927. do
  928. {
  929. i--;
  930. } while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY );
  931. return nTypeArray[i];
  932. }
  933. return 0;
  934. }
  935. sal_Unicode ImpSvNumberformatScan::PreviousChar(sal_uInt16 i)
  936. {
  937. sal_Unicode res = ' ';
  938. if (i > 0 && i < nAnzStrings)
  939. {
  940. i--;
  941. while (i > 0 && ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY
  942. || nTypeArray[i] == NF_SYMBOLTYPE_STRING
  943. || nTypeArray[i] == NF_SYMBOLTYPE_STAR
  944. || nTypeArray[i] == NF_SYMBOLTYPE_BLANK ) )
  945. i--;
  946. if (sStrArray[i].Len() > 0)
  947. res = sStrArray[i].GetChar(xub_StrLen(sStrArray[i].Len()-1));
  948. }
  949. return res;
  950. }
  951. sal_Unicode ImpSvNumberformatScan::NextChar(sal_uInt16 i)
  952. {
  953. sal_Unicode res = ' ';
  954. if (i < nAnzStrings-1)
  955. {
  956. i++;
  957. while (i < nAnzStrings-1 &&
  958. ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY
  959. || nTypeArray[i] == NF_SYMBOLTYPE_STRING
  960. || nTypeArray[i] == NF_SYMBOLTYPE_STAR
  961. || nTypeArray[i] == NF_SYMBOLTYPE_BLANK))
  962. i++;
  963. if (sStrArray[i].Len() > 0)
  964. res = sStrArray[i].GetChar(0);
  965. }
  966. return res;
  967. }
  968. bool ImpSvNumberformatScan::IsLastBlankBeforeFrac(sal_uInt16 i)
  969. {
  970. bool res = true;
  971. if (i < nAnzStrings-1)
  972. {
  973. bool bStop = false;
  974. i++;
  975. while (i < nAnzStrings-1 && !bStop)
  976. {
  977. i++;
  978. if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
  979. sStrArray[i].GetChar(0) == '/')
  980. bStop = true;
  981. else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL &&
  982. sStrArray[i].GetChar(0) == ' ')
  983. res = false;
  984. }
  985. if (!bStop) // kein '/'
  986. res = false;
  987. }
  988. else
  989. res = false; // kein '/' mehr
  990. return res;
  991. }
  992. void ImpSvNumberformatScan::Reset()
  993. {
  994. nAnzStrings = 0;
  995. nAnzResStrings = 0;
  996. #if 0
  997. // ER 20.06.97 14:05 nicht noetig, wenn nAnzStrings beachtet wird
  998. for (size_t i = 0; i < NF_MAX_FORMAT_SYMBOLS; i++)
  999. {
  1000. sStrArray[i].Erase();
  1001. nTypeArray[i] = 0;
  1002. }
  1003. #endif
  1004. eScannedType = NUMBERFORMAT_UNDEFINED;
  1005. nRepPos = 0;
  1006. bExp = false;
  1007. bThousand = false;
  1008. nThousand = 0;
  1009. bDecSep = false;
  1010. nDecPos = -1;
  1011. nExpPos = (sal_uInt16) -1;
  1012. nBlankPos = (sal_uInt16) -1;
  1013. nCntPre = 0;
  1014. nCntPost = 0;
  1015. nCntExp = 0;
  1016. bFrac = false;
  1017. bBlank = false;
  1018. nNatNumModifier = 0;
  1019. }
  1020. bool ImpSvNumberformatScan::Is100SecZero( sal_uInt16 i, bool bHadDecSep )
  1021. {
  1022. sal_uInt16 nIndexPre = PreviousKeyword( i );
  1023. return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS)
  1024. && (bHadDecSep // S, SS ','
  1025. || (i>0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING));
  1026. // SS"any"00 take "any" as a valid decimal separator
  1027. }
  1028. xub_StrLen ImpSvNumberformatScan::ScanType()
  1029. {
  1030. const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
  1031. xub_StrLen nPos = 0;
  1032. sal_uInt16 i = 0;
  1033. short eNewType;
  1034. bool bMatchBracket = false;
  1035. bool bHaveGeneral = false; // if General/Standard encountered
  1036. SkipStrings(i, nPos);
  1037. while (i < nAnzStrings)
  1038. {
  1039. if (nTypeArray[i] > 0)
  1040. { // keyword
  1041. switch (nTypeArray[i])
  1042. {
  1043. case NF_KEY_E: // E
  1044. eNewType = NUMBERFORMAT_SCIENTIFIC;
  1045. break;
  1046. case NF_KEY_AMPM: // AM,A,PM,P
  1047. case NF_KEY_AP:
  1048. case NF_KEY_H: // H
  1049. case NF_KEY_HH: // HH
  1050. case NF_KEY_S: // S
  1051. case NF_KEY_SS: // SS
  1052. eNewType = NUMBERFORMAT_TIME;
  1053. break;
  1054. case NF_KEY_M: // M
  1055. case NF_KEY_MM: // MM
  1056. { // minute or month
  1057. sal_uInt16 nIndexPre = PreviousKeyword(i);
  1058. sal_uInt16 nIndexNex = NextKeyword(i);
  1059. sal_Unicode cChar = PreviousChar(i);
  1060. if (nIndexPre == NF_KEY_H || // H
  1061. nIndexPre == NF_KEY_HH || // HH
  1062. nIndexNex == NF_KEY_S || // S
  1063. nIndexNex == NF_KEY_SS || // SS
  1064. cChar == '[' ) // [M
  1065. {
  1066. eNewType = NUMBERFORMAT_TIME;
  1067. nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5
  1068. }
  1069. else
  1070. eNewType = NUMBERFORMAT_DATE;
  1071. }
  1072. break;
  1073. case NF_KEY_MMM: // MMM
  1074. case NF_KEY_MMMM: // MMMM
  1075. case NF_KEY_MMMMM: // MMMMM
  1076. case NF_KEY_Q: // Q
  1077. case NF_KEY_QQ: // QQ
  1078. case NF_KEY_D: // D
  1079. case NF_KEY_DD: // DD
  1080. case NF_KEY_DDD: // DDD
  1081. case NF_KEY_DDDD: // DDDD
  1082. case NF_KEY_YY: // YY
  1083. case NF_KEY_YYYY: // YYYY
  1084. case NF_KEY_NN: // NN
  1085. case NF_KEY_NNN: // NNN
  1086. case NF_KEY_NNNN: // NNNN
  1087. case NF_KEY_WW : // WW
  1088. case NF_KEY_AAA : // AAA
  1089. case NF_KEY_AAAA : // AAAA
  1090. case NF_KEY_EC : // E
  1091. case NF_KEY_EEC : // EE
  1092. case NF_KEY_G : // G
  1093. case NF_KEY_GG : // GG
  1094. case NF_KEY_GGG : // GGG
  1095. case NF_KEY_R : // R
  1096. case NF_KEY_RR : // RR
  1097. eNewType = NUMBERFORMAT_DATE;
  1098. break;
  1099. case NF_KEY_CCC: // CCC
  1100. eNewType = NUMBERFORMAT_CURRENCY;
  1101. break;
  1102. case NF_KEY_GENERAL: // Standard
  1103. eNewType = NUMBERFORMAT_NUMBER;
  1104. bHaveGeneral = true;
  1105. break;
  1106. default:
  1107. eNewType = NUMBERFORMAT_UNDEFINED;
  1108. break;
  1109. }
  1110. }
  1111. else
  1112. { // control character
  1113. switch ( sStrArray[i].GetChar(0) )
  1114. {
  1115. case '#':
  1116. case '?':
  1117. eNewType = NUMBERFORMAT_NUMBER;
  1118. break;
  1119. case '0':
  1120. {
  1121. if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME )
  1122. {
  1123. if ( Is100SecZero( i, bDecSep ) )
  1124. {
  1125. bDecSep = true; // subsequent 0's
  1126. eNewType = NUMBERFORMAT_TIME;
  1127. }
  1128. else
  1129. return nPos; // Error
  1130. }
  1131. else
  1132. eNewType = NUMBERFORMAT_NUMBER;
  1133. }
  1134. break;
  1135. case '%':
  1136. eNewType = NUMBERFORMAT_PERCENT;
  1137. break;
  1138. case '/':
  1139. eNewType = NUMBERFORMAT_FRACTION;
  1140. break;
  1141. case '[':
  1142. {
  1143. if ( i < nAnzStrings-1 &&
  1144. nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
  1145. sStrArray[i+1].GetChar(0) == '$' )
  1146. { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR
  1147. eNewType = NUMBERFORMAT_CURRENCY;
  1148. bMatchBracket = true;
  1149. }
  1150. else if ( i < nAnzStrings-1 &&
  1151. nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
  1152. sStrArray[i+1].GetChar(0) == '~' )
  1153. { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
  1154. eNewType = NUMBERFORMAT_DATE;
  1155. bMatchBracket = true;
  1156. }
  1157. else
  1158. {
  1159. sal_uInt16 nIndexNex = NextKeyword(i);
  1160. if (nIndexNex == NF_KEY_H || // H
  1161. nIndexNex == NF_KEY_HH || // HH
  1162. nIndexNex == NF_KEY_M || // M
  1163. nIndexNex == NF_KEY_MM || // MM
  1164. nIndexNex == NF_KEY_S || // S
  1165. nIndexNex == NF_KEY_SS ) // SS
  1166. eNewType = NUMBERFORMAT_TIME;
  1167. else
  1168. return nPos; // Error
  1169. }
  1170. }
  1171. break;
  1172. case '@':
  1173. eNewType = NUMBERFORMAT_TEXT;
  1174. break;
  1175. default:
  1176. if ( sStrArray[i] == pLoc->getTime100SecSep() )
  1177. bDecSep = true; // for SS,0
  1178. eNewType = NUMBERFORMAT_UNDEFINED;
  1179. break;
  1180. }
  1181. }
  1182. if (eScannedType == NUMBERFORMAT_UNDEFINED)
  1183. eScannedType = eNewType;
  1184. else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT)
  1185. eScannedType = NUMBERFORMAT_TEXT; // Text bleibt immer Text
  1186. else if (eNewType == NUMBERFORMAT_UNDEFINED)
  1187. { // bleibt wie bisher
  1188. }
  1189. else if (eScannedType != eNewType)
  1190. {
  1191. switch (eScannedType)
  1192. {
  1193. case NUMBERFORMAT_DATE:
  1194. {
  1195. switch (eNewType)
  1196. {
  1197. case NUMBERFORMAT_TIME:
  1198. eScannedType = NUMBERFORMAT_DATETIME;
  1199. break;
  1200. case NUMBERFORMAT_FRACTION: // DD/MM
  1201. break;
  1202. default:
  1203. {
  1204. if (nCurrPos != STRING_NOTFOUND)
  1205. eScannedType = NUMBERFORMAT_UNDEFINED;
  1206. else if ( sStrArray[i] != pFormatter->GetDateSep() )
  1207. return nPos;
  1208. }
  1209. }
  1210. }
  1211. break;
  1212. case NUMBERFORMAT_TIME:
  1213. {
  1214. switch (eNewType)
  1215. {
  1216. case NUMBERFORMAT_DATE:
  1217. eScannedType = NUMBERFORMAT_DATETIME;
  1218. break;
  1219. case NUMBERFORMAT_FRACTION: // MM/SS
  1220. break;
  1221. default:
  1222. {
  1223. if (nCurrPos != STRING_NOTFOUND)
  1224. eScannedType = NUMBERFORMAT_UNDEFINED;
  1225. else if ( sStrArray[i] != pLoc->getTimeSep() )
  1226. return nPos;
  1227. }
  1228. }
  1229. }
  1230. break;
  1231. case NUMBERFORMAT_DATETIME:
  1232. {
  1233. switch (eNewType)
  1234. {
  1235. case NUMBERFORMAT_TIME:
  1236. case NUMBERFORMAT_DATE:
  1237. break;
  1238. case NUMBERFORMAT_FRACTION: // DD/MM
  1239. break;
  1240. default:
  1241. {
  1242. if (nCurrPos != STRING_NOTFOUND)
  1243. eScannedType = NUMBERFORMAT_UNDEFINED;
  1244. else if ( sStrArray[i] != pFormatter->GetDateSep()
  1245. && sStrArray[i] != pLoc->getTimeSep() )
  1246. return nPos;
  1247. }
  1248. }
  1249. }
  1250. break;
  1251. case NUMBERFORMAT_PERCENT:
  1252. {
  1253. switch (eNewType)
  1254. {
  1255. case NUMBERFORMAT_NUMBER: // nur Zahl nach Prozent
  1256. break;
  1257. default:
  1258. return nPos;
  1259. }
  1260. }
  1261. break;
  1262. case NUMBERFORMAT_SCIENTIFIC:
  1263. {
  1264. switch (eNewType)
  1265. {
  1266. case NUMBERFORMAT_NUMBER: // nur Zahl nach E
  1267. break;
  1268. default:
  1269. return nPos;
  1270. }
  1271. }
  1272. break;
  1273. case NUMBERFORMAT_NUMBER:
  1274. {
  1275. switch (eNewType)
  1276. {
  1277. case NUMBERFORMAT_SCIENTIFIC:
  1278. case NUMBERFORMAT_PERCENT:
  1279. case NUMBERFORMAT_FRACTION:
  1280. case NUMBERFORMAT_CURRENCY:
  1281. eScannedType = eNewType;
  1282. break;
  1283. default:
  1284. if (nCurrPos != STRING_NOTFOUND)
  1285. eScannedType = NUMBERFORMAT_UNDEFINED;
  1286. else
  1287. return nPos;
  1288. }
  1289. }
  1290. break;
  1291. case NUMBERFORMAT_FRACTION:
  1292. {
  1293. switch (eNewType)
  1294. {
  1295. case NUMBERFORMAT_NUMBER: // nur Zahl nach Bruch
  1296. break;
  1297. default:
  1298. return nPos;
  1299. }
  1300. }
  1301. break;
  1302. default:
  1303. break;
  1304. }
  1305. }
  1306. nPos = nPos + sStrArray[i].Len(); // Korrekturposition
  1307. i++;
  1308. if ( bMatchBracket )
  1309. { // no type detection inside of matching brackets if [$...], [~...]
  1310. while ( bMatchBracket && i < nAnzStrings )
  1311. {
  1312. if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL
  1313. && sStrArray[i].GetChar(0) == ']' )
  1314. bMatchBracket = false;
  1315. else
  1316. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1317. nPos = nPos + sStrArray[i].Len();
  1318. i++;
  1319. }
  1320. if ( bMatchBracket )
  1321. return nPos; // missing closing bracket at end of code
  1322. }
  1323. SkipStrings(i, nPos);
  1324. }
  1325. if ((eScannedType == NUMBERFORMAT_NUMBER || eScannedType == NUMBERFORMAT_UNDEFINED)
  1326. && nCurrPos != STRING_NOTFOUND && !bHaveGeneral)
  1327. eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency
  1328. if (eScannedType == NUMBERFORMAT_UNDEFINED)
  1329. eScannedType = NUMBERFORMAT_DEFINED;
  1330. return 0; // Alles ok
  1331. }
  1332. bool ImpSvNumberformatScan::InsertSymbol( sal_uInt16 & nPos, svt::NfSymbolType eType, const String& rStr )
  1333. {
  1334. if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings)
  1335. return false;
  1336. if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY)
  1337. --nPos; // reuse position
  1338. else
  1339. {
  1340. if ((size_t) (nAnzStrings + 1) >= NF_MAX_FORMAT_SYMBOLS)
  1341. return false;
  1342. ++nAnzStrings;
  1343. for (size_t i = nAnzStrings; i > nPos; --i)
  1344. {
  1345. nTypeArray[i] = nTypeArray[i-1];
  1346. sStrArray[i] = sStrArray[i-1];
  1347. }
  1348. }
  1349. ++nAnzResStrings;
  1350. nTypeArray[nPos] = static_cast<short>(eType);
  1351. sStrArray[nPos] = rStr;
  1352. return true;
  1353. }
  1354. int ImpSvNumberformatScan::FinalScanGetCalendar( xub_StrLen& nPos, sal_uInt16& i,
  1355. sal_uInt16& rAnzResStrings )
  1356. {
  1357. if ( sStrArray[i].GetChar(0) == '[' &&
  1358. i < nAnzStrings-1 &&
  1359. nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
  1360. sStrArray[i+1].GetChar(0) == '~' )
  1361. { // [~calendarID]
  1362. // as of SV_NUMBERFORMATTER_VERSION_CALENDAR
  1363. nPos = nPos + sStrArray[i].Len(); // [
  1364. nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
  1365. nPos = nPos + sStrArray[++i].Len(); // ~
  1366. sStrArray[i-1] += sStrArray[i]; // [~
  1367. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1368. rAnzResStrings--;
  1369. if ( ++i >= nAnzStrings )
  1370. return -1; // error
  1371. nPos = nPos + sStrArray[i].Len(); // calendarID
  1372. String& rStr = sStrArray[i];
  1373. nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert
  1374. i++;
  1375. while ( i < nAnzStrings &&
  1376. sStrArray[i].GetChar(0) != ']' )
  1377. {
  1378. nPos = nPos + sStrArray[i].Len();
  1379. rStr += sStrArray[i];
  1380. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1381. rAnzResStrings--;
  1382. i++;
  1383. }
  1384. if ( rStr.Len() && i < nAnzStrings &&
  1385. sStrArray[i].GetChar(0) == ']' )
  1386. {
  1387. nTypeArray[i] = NF_SYMBOLTYPE_CALDEL;
  1388. nPos = nPos + sStrArray[i].Len();
  1389. i++;
  1390. }
  1391. else
  1392. return -1; // error
  1393. return 1;
  1394. }
  1395. return 0;
  1396. }
  1397. xub_StrLen ImpSvNumberformatScan::FinalScan( String& rString )
  1398. {
  1399. const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
  1400. // save values for convert mode
  1401. String sOldDecSep = pFormatter->GetNumDecimalSep();
  1402. String sOldThousandSep = pFormatter->GetNumThousandSep();
  1403. String sOldDateSep = pFormatter->GetDateSep();
  1404. String sOldTimeSep = pLoc->getTimeSep();
  1405. String sOldTime100SecSep= pLoc->getTime100SecSep();
  1406. String sOldCurSymbol = GetCurSymbol();
  1407. rtl::OUString sOldCurString = GetCurString();
  1408. sal_Unicode cOldKeyH = sKeyword[NF_KEY_H].GetChar(0);
  1409. sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI].GetChar(0);
  1410. sal_Unicode cOldKeyS = sKeyword[NF_KEY_S].GetChar(0);
  1411. // If the group separator is a Non-Breaking Space (French) continue with a
  1412. // normal space instead so queries on space work correctly.
  1413. // The format string is adjusted to allow both.
  1414. // For output of the format code string the LocaleData characters are used.
  1415. if ( sOldThousandSep.GetChar(0) == cNonBreakingSpace && sOldThousandSep.Len() == 1 )
  1416. sOldThousandSep = ' ';
  1417. // change locale data et al
  1418. if (bConvertMode)
  1419. {
  1420. pFormatter->ChangeIntl(eNewLnge);
  1421. //! pointer may have changed
  1422. pLoc = pFormatter->GetLocaleData();
  1423. //! init new keywords
  1424. InitKeywords();
  1425. }
  1426. const CharClass* pChrCls = pFormatter->GetCharClass();
  1427. xub_StrLen nPos = 0; // error correction position
  1428. sal_uInt16 i = 0; // symbol loop counter
  1429. sal_uInt16 nCounter = 0; // counts digits
  1430. nAnzResStrings = nAnzStrings; // counts remaining symbols
  1431. bDecSep = false; // reset in case already used in TypeCheck
  1432. bool bThaiT = false; // Thai T NatNum modifier present
  1433. switch (eScannedType)
  1434. {
  1435. case NUMBERFORMAT_TEXT:
  1436. case NUMBERFORMAT_DEFINED:
  1437. {
  1438. while (i < nAnzStrings)
  1439. {
  1440. switch (nTypeArray[i])
  1441. {
  1442. case NF_SYMBOLTYPE_BLANK:
  1443. case NF_SYMBOLTYPE_STAR:
  1444. break;
  1445. case NF_KEY_GENERAL : // #77026# "General" is the same as "@"
  1446. break;
  1447. default:
  1448. {
  1449. if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL ||
  1450. sStrArray[i].GetChar(0) != '@' )
  1451. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1452. }
  1453. break;
  1454. }
  1455. nPos = nPos + sStrArray[i].Len();
  1456. i++;
  1457. } // of while
  1458. }
  1459. break;
  1460. case NUMBERFORMAT_NUMBER:
  1461. case NUMBERFORMAT_PERCENT:
  1462. case NUMBERFORMAT_CURRENCY:
  1463. case NUMBERFORMAT_SCIENTIFIC:
  1464. case NUMBERFORMAT_FRACTION:
  1465. {
  1466. while (i < nAnzStrings)
  1467. {
  1468. // TODO: rechecking eScannedType is unnecessary.
  1469. // This switch-case is for eScannedType == NUMBERFORMAT_FRACTION anyway
  1470. if (eScannedType == NUMBERFORMAT_FRACTION && // special case
  1471. nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/#
  1472. StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden
  1473. StringEqualsChar( sStrArray[i], ' ' ) &&
  1474. !bFrac &&
  1475. IsLastBlankBeforeFrac(i) )
  1476. {
  1477. nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string
  1478. } // kein Taus.p.
  1479. if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK ||
  1480. nTypeArray[i] == NF_SYMBOLTYPE_STAR ||
  1481. nTypeArray[i] == NF_KEY_CCC || // CCC
  1482. nTypeArray[i] == NF_KEY_GENERAL ) // Standard
  1483. {
  1484. if (nTypeArray[i] == NF_KEY_GENERAL)
  1485. {
  1486. nThousand = FLAG_STANDARD_IN_FORMAT;
  1487. if ( bConvertMode )
  1488. sStrArray[i] = sNameStandardFormat;
  1489. }
  1490. nPos = nPos + sStrArray[i].Len();
  1491. i++;
  1492. }
  1493. else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // Strings oder
  1494. nTypeArray[i] > 0) // Keywords
  1495. {
  1496. if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
  1497. nTypeArray[i] == NF_KEY_E) // E+
  1498. {
  1499. if (bExp) // doppelt
  1500. return nPos;
  1501. bExp = true;
  1502. nExpPos = i;
  1503. if (bDecSep)
  1504. nCntPost = nCounter;
  1505. else
  1506. nCntPre = nCounter;
  1507. nCounter = 0;
  1508. nTypeArray[i] = NF_SYMBOLTYPE_EXP;
  1509. }
  1510. else if (eScannedType == NUMBERFORMAT_FRACTION &&
  1511. sStrArray[i].GetChar(0) == ' ')
  1512. {
  1513. if (!bBlank && !bFrac) // nicht doppelt oder hinter /
  1514. {
  1515. if (bDecSep && nCounter > 0) // Nachkommastellen
  1516. return nPos; // Fehler
  1517. bBlank = true;
  1518. nBlankPos = i;
  1519. nCntPre = nCounter;
  1520. nCounter = 0;
  1521. }
  1522. nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK;
  1523. }
  1524. else if (nTypeArray[i] == NF_KEY_THAI_T)
  1525. {
  1526. bThaiT = true;
  1527. sStrArray[i] = sKeyword[nTypeArray[i]];
  1528. }
  1529. else if (sStrArray[i].GetChar(0) >= '0' &&
  1530. sStrArray[i].GetChar(0) <= '9')
  1531. {
  1532. rtl::OUString sDiv;
  1533. sal_uInt16 j = i;
  1534. while(j < nAnzStrings)
  1535. sDiv += sStrArray[j++];
  1536. if (rtl::OUString::valueOf(sDiv.toInt32()) == sDiv)
  1537. {
  1538. /* Found a Divisor */
  1539. while (i < j)
  1540. nTypeArray[i++] = NF_SYMBOLTYPE_FRAC_FDIV;
  1541. i = j - 1; // Stop the loop
  1542. if (nCntPost)
  1543. nCounter = nCntPost;
  1544. else if (nCntPre)
  1545. nCounter = nCntPre;
  1546. if (!nCntPre)
  1547. nCntPre++;
  1548. }
  1549. }
  1550. else
  1551. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1552. nPos = nPos + sStrArray[i].Len();
  1553. i++;
  1554. }
  1555. else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL)
  1556. {
  1557. sal_Unicode cHere = sStrArray[i].GetChar(0);
  1558. // Handle not pre-known separators in switch.
  1559. sal_Unicode cSimplified;
  1560. if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere))
  1561. cSimplified = ',';
  1562. else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere))
  1563. cSimplified = '.';
  1564. else
  1565. cSimplified = cHere;
  1566. switch ( cSimplified )
  1567. {
  1568. case '#':
  1569. case '0':
  1570. case '?':
  1571. {
  1572. if (nThousand > 0) // #... #
  1573. return nPos; // Fehler
  1574. else if (bFrac && cHere == '0')
  1575. return nPos; // 0 im Nenner
  1576. nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
  1577. String& rStr = sStrArray[i];
  1578. nPos = nPos + rStr.Len();
  1579. i++;
  1580. nCounter++;
  1581. while (i < nAnzStrings &&
  1582. (sStrArray[i].GetChar(0) == '#' ||
  1583. sStrArray[i].GetChar(0) == '0' ||
  1584. sStrArray[i].GetChar(0) == '?')
  1585. )
  1586. {
  1587. nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
  1588. nPos = nPos + sStrArray[i].Len();
  1589. nCounter++;
  1590. i++;
  1591. }
  1592. }
  1593. break;
  1594. case '-':
  1595. {
  1596. if ( bDecSep && nDecPos+1 == i &&
  1597. nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP )
  1598. { // "0.--"
  1599. nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
  1600. String& rStr = sStrArray[i];
  1601. nPos = nPos + rStr.Len();
  1602. i++;
  1603. nCounter++;
  1604. while (i < nAnzStrings &&
  1605. (sStrArray[i].GetChar(0) == '-') )
  1606. {
  1607. // If more than two dashes are present in
  1608. // currency formats the last dash will be
  1609. // interpreted literally as a minus sign.
  1610. // Has to be this ugly. Period.
  1611. if ( eScannedType == NUMBERFORMAT_CURRENCY
  1612. && rStr.Len() >= 2 &&
  1613. (i == nAnzStrings-1 ||
  1614. sStrArray[i+1].GetChar(0) != '-') )
  1615. break;
  1616. rStr += sStrArray[i];
  1617. nPos = nPos + sStrArray[i].Len();
  1618. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1619. nAnzResStrings--;
  1620. nCounter++;
  1621. i++;
  1622. }
  1623. }
  1624. else
  1625. {
  1626. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1627. nPos = nPos + sStrArray[i].Len();
  1628. i++;
  1629. }
  1630. }
  1631. break;
  1632. case '.':
  1633. case ',':
  1634. case '\'':
  1635. case ' ':
  1636. {
  1637. sal_Unicode cSep = cHere; // remember
  1638. if ( StringEqualsChar( sOldThousandSep, cSep ) )
  1639. {
  1640. // previous char with skip empty
  1641. sal_Unicode cPre = PreviousChar(i);
  1642. sal_Unicode cNext;
  1643. if (bExp || bBlank || bFrac)
  1644. { // after E, / or ' '
  1645. if ( !StringEqualsChar( sOldThousandSep, ' ' ) )
  1646. {
  1647. nPos = nPos + sStrArray[i].Len();
  1648. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1649. nAnzResStrings--;
  1650. i++; // eat it
  1651. }
  1652. else
  1653. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1654. }
  1655. else if (i > 0 && i < nAnzStrings-1 &&
  1656. (cPre == '#' || cPre == '0') &&
  1657. ((cNext = NextChar(i)) == '#' || cNext == '0')
  1658. ) // #,#
  1659. {
  1660. nPos = nPos + sStrArray[i].Len();
  1661. if (!bThousand) // only once
  1662. bThousand = true;
  1663. // Eat it, will be reinserted at proper
  1664. // grouping positions further down.
  1665. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1666. nAnzResStrings--;
  1667. i++;
  1668. }
  1669. else if (i > 0 && (cPre == '#' || cPre == '0')
  1670. && PreviousType(i) == NF_SYMBOLTYPE_DIGIT
  1671. && nThousand < FLAG_STANDARD_IN_FORMAT )
  1672. { // #,,,,
  1673. if ( StringEqualsChar( sOldThousandSep, ' ' ) )
  1674. { // strange, those French..
  1675. bool bFirst = true;
  1676. String& rStr = sStrArray[i];
  1677. // set a hard Non-Breaking Space or ConvertMode
  1678. const String& rSepF = pFormatter->GetNumThousandSep();
  1679. while ( i < nAnzStrings
  1680. && sStrArray[i] == sOldThousandSep
  1681. && StringEqualsChar( sOldThousandSep, NextChar(i) ) )
  1682. { // last was a space or another space
  1683. // is following => separator
  1684. nPos = nPos + sStrArray[i].Len();
  1685. if ( bFirst )
  1686. {
  1687. bFirst = false;
  1688. rStr = rSepF;
  1689. nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
  1690. }
  1691. else
  1692. {
  1693. rStr += rSepF;
  1694. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1695. nAnzResStrings--;
  1696. }
  1697. nThousand++;
  1698. i++;
  1699. }
  1700. if ( i < nAnzStrings-1
  1701. && sStrArray[i] == sOldThousandSep )
  1702. { // something following last space
  1703. // => space if currency contained,
  1704. // else separator
  1705. nPos = nPos + sStrArray[i].Len();
  1706. if ( (nPos <= nCurrPos &&
  1707. nCurrPos < nPos + sStrArray[i+1].Len())
  1708. || nTypeArray[i+1] == NF_KEY_CCC
  1709. || (i < nAnzStrings-2 &&
  1710. sStrArray[i+1].GetChar(0) == '[' &&
  1711. sStrArray[i+2].GetChar(0) == '$') )
  1712. {
  1713. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1714. }
  1715. else
  1716. {
  1717. if ( bFirst )
  1718. {
  1719. bFirst = false;
  1720. rStr = rSepF;
  1721. nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
  1722. }
  1723. else
  1724. {
  1725. rStr += rSepF;
  1726. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1727. nAnzResStrings--;
  1728. }
  1729. nThousand++;
  1730. }
  1731. i++;
  1732. }
  1733. }
  1734. else
  1735. {
  1736. do
  1737. {
  1738. nThousand++;
  1739. nTypeArray[i] = NF_SYMBOLTYPE_THSEP;
  1740. nPos = nPos + sStrArray[i].Len();
  1741. sStrArray[i] = pFormatter->GetNumThousandSep();
  1742. i++;
  1743. } while (i < nAnzStrings &&
  1744. sStrArray[i] == sOldThousandSep);
  1745. }
  1746. }
  1747. else // any grsep
  1748. {
  1749. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1750. String& rStr = sStrArray[i];
  1751. nPos = nPos + rStr.Len();
  1752. i++;
  1753. while ( i < nAnzStrings &&
  1754. sStrArray[i] == sOldThousandSep )
  1755. {
  1756. rStr += sStrArray[i];
  1757. nPos = nPos + sStrArray[i].Len();
  1758. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1759. nAnzResStrings--;
  1760. i++;
  1761. }
  1762. }
  1763. }
  1764. else if ( StringEqualsChar( sOldDecSep, cSep ) )
  1765. {
  1766. if (bBlank || bFrac) // . behind / or ' '
  1767. return nPos; // error
  1768. else if (bExp) // behind E
  1769. {
  1770. nPos = nPos + sStrArray[i].Len();
  1771. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1772. nAnzResStrings--;
  1773. i++; // eat it
  1774. }
  1775. else if (bDecSep) // any .
  1776. {
  1777. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1778. String& rStr = sStrArray[i];
  1779. nPos = nPos + rStr.Len();
  1780. i++;
  1781. while ( i < nAnzStrings &&
  1782. sStrArray[i] == sOldDecSep )
  1783. {
  1784. rStr += sStrArray[i];
  1785. nPos = nPos + sStrArray[i].Len();
  1786. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1787. nAnzResStrings--;
  1788. i++;
  1789. }
  1790. }
  1791. else
  1792. {
  1793. nPos = nPos + sStrArray[i].Len();
  1794. nTypeArray[i] = NF_SYMBOLTYPE_DECSEP;
  1795. sStrArray[i] = pFormatter->GetNumDecimalSep();
  1796. bDecSep = true;
  1797. nDecPos = i;
  1798. nCntPre = nCounter;
  1799. nCounter = 0;
  1800. i++;
  1801. }
  1802. } // of else = DecSep
  1803. else // . without meaning
  1804. {
  1805. if (cSep == ' ' &&
  1806. eScannedType == NUMBERFORMAT_FRACTION &&
  1807. StringEqualsChar( sStrArray[i], ' ' ) )
  1808. {
  1809. if (!bBlank && !bFrac) // no dups
  1810. { // or behind /
  1811. if (bDecSep && nCounter > 0)// dec.
  1812. return nPos; // error
  1813. bBlank = true;
  1814. nBlankPos = i;
  1815. nCntPre = nCounter;
  1816. nCounter = 0;
  1817. }
  1818. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1819. nPos = nPos + sStrArray[i].Len();
  1820. }
  1821. else
  1822. {
  1823. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1824. String& rStr = sStrArray[i];
  1825. nPos = nPos + rStr.Len();
  1826. i++;
  1827. while (i < nAnzStrings &&
  1828. StringEqualsChar( sStrArray[i], cSep ) )
  1829. {
  1830. rStr += sStrArray[i];
  1831. nPos = nPos + sStrArray[i].Len();
  1832. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1833. nAnzResStrings--;
  1834. i++;
  1835. }
  1836. }
  1837. }
  1838. }
  1839. break;
  1840. case '/':
  1841. {
  1842. if (eScannedType == NUMBERFORMAT_FRACTION)
  1843. {
  1844. if ( i == 0 ||
  1845. (nTypeArray[i-1] != NF_SYMBOLTYPE_DIGIT &&
  1846. nTypeArray[i-1] != NF_SYMBOLTYPE_EMPTY) )
  1847. return nPos ? nPos : 1; // /? not allowed
  1848. else if (!bFrac || (bDecSep && nCounter > 0))
  1849. {
  1850. bFrac = true;
  1851. nCntPost = nCounter;
  1852. nCounter = 0;
  1853. nTypeArray[i] = NF_SYMBOLTYPE_FRAC;
  1854. nPos = nPos + sStrArray[i].Len();
  1855. i++;
  1856. }
  1857. else // / doppelt od. , imZaehl
  1858. return nPos; // Fehler
  1859. }
  1860. else
  1861. {
  1862. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1863. nPos = nPos + sStrArray[i].Len();
  1864. i++;
  1865. }
  1866. }
  1867. break;
  1868. case '[' :
  1869. {
  1870. if ( eScannedType == NUMBERFORMAT_CURRENCY &&
  1871. i < nAnzStrings-1 &&
  1872. nTypeArray[i+1] == NF_SYMBOLTYPE_STRING &&
  1873. sStrArray[i+1].GetChar(0) == '$' )
  1874. { // [$DM-xxx]
  1875. // ab SV_NUMBERFORMATTER_VERSION_NEW_CURR
  1876. nPos = nPos + sStrArray[i].Len(); // [
  1877. nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
  1878. nPos = nPos + sStrArray[++i].Len(); // $
  1879. sStrArray[i-1] += sStrArray[i]; // [$
  1880. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1881. nAnzResStrings--;
  1882. if ( ++i >= nAnzStrings )
  1883. return nPos; // Fehler
  1884. nPos = nPos + sStrArray[i].Len(); // DM
  1885. String& rStr = sStrArray[i];
  1886. String* pStr = &sStrArray[i];
  1887. nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // wandeln
  1888. bool bHadDash = false;
  1889. i++;
  1890. while ( i < nAnzStrings &&
  1891. sStrArray[i].GetChar(0) != ']' )
  1892. {
  1893. nPos = nPos + sStrArray[i].Len();
  1894. if ( bHadDash )
  1895. {
  1896. *pStr += sStrArray[i];
  1897. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1898. nAnzResStrings--;
  1899. }
  1900. else
  1901. {
  1902. if ( sStrArray[i].GetChar(0) == '-' )
  1903. {
  1904. bHadDash = true;
  1905. pStr = &sStrArray[i];
  1906. nTypeArray[i] = NF_SYMBOLTYPE_CURREXT;
  1907. }
  1908. else
  1909. {
  1910. *pStr += sStrArray[i];
  1911. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  1912. nAnzResStrings--;
  1913. }
  1914. }
  1915. i++;
  1916. }
  1917. if ( rStr.Len() && i < nAnzStrings &&
  1918. sStrArray[i].GetChar(0) == ']' )
  1919. {
  1920. nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL;
  1921. nPos = nPos + sStrArray[i].Len();
  1922. i++;
  1923. }
  1924. else
  1925. return nPos; // Fehler
  1926. }
  1927. else
  1928. {
  1929. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1930. nPos = nPos + sStrArray[i].Len();
  1931. i++;
  1932. }
  1933. }
  1934. break;
  1935. default: // andere Dels
  1936. {
  1937. if (eScannedType == NUMBERFORMAT_PERCENT &&
  1938. cHere == '%')
  1939. nTypeArray[i] = NF_SYMBOLTYPE_PERCENT;
  1940. else
  1941. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  1942. nPos = nPos + sStrArray[i].Len();
  1943. i++;
  1944. }
  1945. break;
  1946. } // of switch (Del)
  1947. } // of else Del
  1948. else
  1949. {
  1950. SAL_WARN( "svl.numbers", "unknown NF_SYMBOLTYPE_..." );
  1951. nPos = nPos + sStrArray[i].Len();
  1952. i++;
  1953. }
  1954. } // of while
  1955. if (eScannedType == NUMBERFORMAT_FRACTION)
  1956. {
  1957. if (bFrac)
  1958. nCntExp = nCounter;
  1959. else if (bBlank)
  1960. nCntPost = nCounter;
  1961. else
  1962. nCntPre = nCounter;
  1963. }
  1964. else
  1965. {
  1966. if (bExp)
  1967. nCntExp = nCounter;
  1968. else if (bDecSep)
  1969. nCntPost = nCounter;
  1970. else
  1971. nCntPre = nCounter;
  1972. }
  1973. if (bThousand) // Expansion of grouping separators
  1974. {
  1975. sal_uInt16 nMaxPos;
  1976. if (bFrac)
  1977. {
  1978. if (bBlank)
  1979. nMaxPos = nBlankPos;
  1980. else
  1981. nMaxPos = 0; // no grouping
  1982. }
  1983. else if (bDecSep) // decimal separator present
  1984. nMaxPos = nDecPos;
  1985. else if (bExp) // 'E' exponent present
  1986. nMaxPos = nExpPos;
  1987. else // up to end
  1988. nMaxPos = i;
  1989. // Insert separators at proper positions.
  1990. xub_StrLen nCount = 0;
  1991. utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping());
  1992. size_t nFirstDigitSymbol = nMaxPos;
  1993. size_t nFirstGroupingSymbol = nMaxPos;
  1994. i = nMaxPos;
  1995. while (i-- > 0)
  1996. {
  1997. if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
  1998. {
  1999. nFirstDigitSymbol = i;
  2000. nCount = nCount + sStrArray[i].Len(); // MSC converts += to int and then warns, so ...
  2001. // Insert separator only if not leftmost symbol.
  2002. if (i > 0 && nCount >= aGrouping.getPos())
  2003. {
  2004. DBG_ASSERT( sStrArray[i].Len() == 1,
  2005. "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion");
  2006. if (!InsertSymbol( i, NF_SYMBOLTYPE_THSEP,
  2007. pFormatter->GetNumThousandSep()))
  2008. // nPos isn't correct here, but signals error
  2009. return nPos;
  2010. // i may have been decremented by 1
  2011. nFirstDigitSymbol = i + 1;
  2012. nFirstGroupingSymbol = i;
  2013. aGrouping.advance();
  2014. }
  2015. }
  2016. }
  2017. // Generated something like "string",000; remove separator again.
  2018. if (nFirstGroupingSymbol < nFirstDigitSymbol)
  2019. {
  2020. nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY;
  2021. nAnzResStrings--;
  2022. }
  2023. }
  2024. // Combine digits into groups to save memory (Info will be copied
  2025. // later, taking only non-empty symbols).
  2026. for (i = 0; i < nAnzStrings; ++i)
  2027. {
  2028. if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
  2029. {
  2030. String& rStr = sStrArray[i];
  2031. while (++i < nAnzStrings &&
  2032. nTypeArray[i] == NF_SYMBOLTYPE_DIGIT)
  2033. {
  2034. rStr += sStrArray[i];
  2035. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  2036. nAnzResStrings--;
  2037. }
  2038. }
  2039. }
  2040. }
  2041. break; // of NUMBERFORMAT_NUMBER
  2042. case NUMBERFORMAT_DATE:
  2043. {
  2044. while (i < nAnzStrings)
  2045. {
  2046. switch (nTypeArray[i])
  2047. {
  2048. case NF_SYMBOLTYPE_BLANK:
  2049. case NF_SYMBOLTYPE_STAR:
  2050. case NF_SYMBOLTYPE_STRING:
  2051. nPos = nPos + sStrArray[i].Len();
  2052. i++;
  2053. break;
  2054. case NF_SYMBOLTYPE_DEL:
  2055. {
  2056. int nCalRet;
  2057. if (sStrArray[i] == sOldDateSep)
  2058. {
  2059. nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
  2060. nPos = nPos + sStrArray[i].Len();
  2061. if (bConvertMode)
  2062. sStrArray[i] = pFormatter->GetDateSep();
  2063. i++;
  2064. }
  2065. else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
  2066. {
  2067. if ( nCalRet < 0 )
  2068. return nPos; // error
  2069. }
  2070. else
  2071. {
  2072. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2073. nPos = nPos + sStrArray[i].Len();
  2074. i++;
  2075. }
  2076. }
  2077. break;
  2078. case NF_KEY_THAI_T :
  2079. bThaiT = true;
  2080. // fall thru
  2081. case NF_KEY_M: // M
  2082. case NF_KEY_MM: // MM
  2083. case NF_KEY_MMM: // MMM
  2084. case NF_KEY_MMMM: // MMMM
  2085. case NF_KEY_MMMMM: // MMMMM
  2086. case NF_KEY_Q: // Q
  2087. case NF_KEY_QQ: // QQ
  2088. case NF_KEY_D: // D
  2089. case NF_KEY_DD: // DD
  2090. case NF_KEY_DDD: // DDD
  2091. case NF_KEY_DDDD: // DDDD
  2092. case NF_KEY_YY: // YY
  2093. case NF_KEY_YYYY: // YYYY
  2094. case NF_KEY_NN: // NN
  2095. case NF_KEY_NNN: // NNN
  2096. case NF_KEY_NNNN: // NNNN
  2097. case NF_KEY_WW : // WW
  2098. case NF_KEY_AAA : // AAA
  2099. case NF_KEY_AAAA : // AAAA
  2100. case NF_KEY_EC : // E
  2101. case NF_KEY_EEC : // EE
  2102. case NF_KEY_G : // G
  2103. case NF_KEY_GG : // GG
  2104. case NF_KEY_GGG : // GGG
  2105. case NF_KEY_R : // R
  2106. case NF_KEY_RR : // RR
  2107. sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
  2108. nPos = nPos + sStrArray[i].Len();
  2109. i++;
  2110. break;
  2111. default: // andere Keywords
  2112. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2113. nPos = nPos + sStrArray[i].Len();
  2114. i++;
  2115. break;
  2116. }
  2117. } // of while
  2118. }
  2119. break; // of NUMBERFORMAT_DATE
  2120. case NUMBERFORMAT_TIME:
  2121. {
  2122. while (i < nAnzStrings)
  2123. {
  2124. switch (nTypeArray[i])
  2125. {
  2126. case NF_SYMBOLTYPE_BLANK:
  2127. case NF_SYMBOLTYPE_STAR:
  2128. {
  2129. nPos = nPos + sStrArray[i].Len();
  2130. i++;
  2131. }
  2132. break;
  2133. case NF_SYMBOLTYPE_DEL:
  2134. {
  2135. switch( sStrArray[i].GetChar(0) )
  2136. {
  2137. case '0':
  2138. {
  2139. if ( Is100SecZero( i, bDecSep ) )
  2140. {
  2141. bDecSep = true;
  2142. nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
  2143. String& rStr = sStrArray[i];
  2144. i++;
  2145. nPos = nPos + sStrArray[i].Len();
  2146. nCounter++;
  2147. while (i < nAnzStrings &&
  2148. sStrArray[i].GetChar(0) == '0')
  2149. {
  2150. rStr += sStrArray[i];
  2151. nPos = nPos + sStrArray[i].Len();
  2152. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  2153. nAnzResStrings--;
  2154. nCounter++;
  2155. i++;
  2156. }
  2157. }
  2158. else
  2159. return nPos;
  2160. }
  2161. break;
  2162. case '#':
  2163. case '?':
  2164. return nPos;
  2165. case '[':
  2166. {
  2167. if (bThousand) // doppelt
  2168. return nPos;
  2169. bThousand = true; // bei Time frei
  2170. sal_Unicode cChar = pChrCls->uppercase(rtl::OUString(NextChar(i)))[0];
  2171. if ( cChar == cOldKeyH )
  2172. nThousand = 1; // H
  2173. else if ( cChar == cOldKeyMI )
  2174. nThousand = 2; // M
  2175. else if ( cChar == cOldKeyS )
  2176. nThousand = 3; // S
  2177. else
  2178. return nPos;
  2179. nPos = nPos + sStrArray[i].Len();
  2180. i++;
  2181. }
  2182. break;
  2183. case ']':
  2184. {
  2185. if (!bThousand) // kein [ vorher
  2186. return nPos;
  2187. nPos = nPos + sStrArray[i].Len();
  2188. i++;
  2189. }
  2190. break;
  2191. default:
  2192. {
  2193. nPos = nPos + sStrArray[i].Len();
  2194. if ( sStrArray[i] == sOldTimeSep )
  2195. {
  2196. nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
  2197. if ( bConvertMode )
  2198. sStrArray[i] = pLoc->getTimeSep();
  2199. }
  2200. else if ( sStrArray[i] == sOldTime100SecSep )
  2201. {
  2202. bDecSep = true;
  2203. nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
  2204. if ( bConvertMode )
  2205. sStrArray[i] = pLoc->getTime100SecSep();
  2206. }
  2207. else
  2208. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2209. i++;
  2210. }
  2211. break;
  2212. }
  2213. }
  2214. break;
  2215. case NF_SYMBOLTYPE_STRING:
  2216. {
  2217. nPos = nPos + sStrArray[i].Len();
  2218. i++;
  2219. }
  2220. break;
  2221. case NF_KEY_AMPM: // AM/PM
  2222. case NF_KEY_AP: // A/P
  2223. {
  2224. bExp = true; // missbraucht fuer A/P
  2225. sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
  2226. nPos = nPos + sStrArray[i].Len();
  2227. i++;
  2228. }
  2229. break;
  2230. case NF_KEY_THAI_T :
  2231. bThaiT = true;
  2232. // fall thru
  2233. case NF_KEY_MI: // M
  2234. case NF_KEY_MMI: // MM
  2235. case NF_KEY_H: // H
  2236. case NF_KEY_HH: // HH
  2237. case NF_KEY_S: // S
  2238. case NF_KEY_SS: // SS
  2239. {
  2240. sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
  2241. nPos = nPos + sStrArray[i].Len();
  2242. i++;
  2243. }
  2244. break;
  2245. default: // andere Keywords
  2246. {
  2247. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2248. nPos = nPos + sStrArray[i].Len();
  2249. i++;
  2250. }
  2251. break;
  2252. }
  2253. } // of while
  2254. nCntPost = nCounter; // Zaehler der Nullen
  2255. if (bExp)
  2256. nCntExp = 1; // merkt AM/PM
  2257. }
  2258. break; // of NUMBERFORMAT_TIME
  2259. case NUMBERFORMAT_DATETIME:
  2260. {
  2261. bool bTimePart = false;
  2262. while (i < nAnzStrings)
  2263. {
  2264. switch (nTypeArray[i])
  2265. {
  2266. case NF_SYMBOLTYPE_BLANK:
  2267. case NF_SYMBOLTYPE_STAR:
  2268. case NF_SYMBOLTYPE_STRING:
  2269. nPos = nPos + sStrArray[i].Len();
  2270. i++;
  2271. break;
  2272. case NF_SYMBOLTYPE_DEL:
  2273. {
  2274. int nCalRet;
  2275. if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 )
  2276. {
  2277. if ( nCalRet < 0 )
  2278. return nPos; // error
  2279. }
  2280. else
  2281. {
  2282. switch( sStrArray[i].GetChar(0) )
  2283. {
  2284. case '0':
  2285. {
  2286. if ( bTimePart && Is100SecZero( i, bDecSep ) )
  2287. {
  2288. bDecSep = true;
  2289. nTypeArray[i] = NF_SYMBOLTYPE_DIGIT;
  2290. String& rStr = sStrArray[i];
  2291. i++;
  2292. nPos = nPos + sStrArray[i].Len();
  2293. nCounter++;
  2294. while (i < nAnzStrings &&
  2295. sStrArray[i].GetChar(0) == '0')
  2296. {
  2297. rStr += sStrArray[i];
  2298. nPos = nPos + sStrArray[i].Len();
  2299. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  2300. nAnzResStrings--;
  2301. nCounter++;
  2302. i++;
  2303. }
  2304. }
  2305. else
  2306. return nPos;
  2307. }
  2308. break;
  2309. case '#':
  2310. case '?':
  2311. return nPos;
  2312. default:
  2313. {
  2314. nPos = nPos + sStrArray[i].Len();
  2315. if (bTimePart)
  2316. {
  2317. if ( sStrArray[i] == sOldTimeSep )
  2318. {
  2319. nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP;
  2320. if ( bConvertMode )
  2321. sStrArray[i] = pLoc->getTimeSep();
  2322. }
  2323. else if ( sStrArray[i] == sOldTime100SecSep )
  2324. {
  2325. bDecSep = true;
  2326. nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP;
  2327. if ( bConvertMode )
  2328. sStrArray[i] = pLoc->getTime100SecSep();
  2329. }
  2330. else
  2331. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2332. }
  2333. else
  2334. {
  2335. if ( sStrArray[i] == sOldDateSep )
  2336. {
  2337. nTypeArray[i] = NF_SYMBOLTYPE_DATESEP;
  2338. if (bConvertMode)
  2339. sStrArray[i] = pFormatter->GetDateSep();
  2340. }
  2341. else
  2342. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2343. }
  2344. i++;
  2345. }
  2346. }
  2347. }
  2348. }
  2349. break;
  2350. case NF_KEY_AMPM: // AM/PM
  2351. case NF_KEY_AP: // A/P
  2352. {
  2353. bTimePart = true;
  2354. bExp = true; // missbraucht fuer A/P
  2355. sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
  2356. nPos = nPos + sStrArray[i].Len();
  2357. i++;
  2358. }
  2359. break;
  2360. case NF_KEY_MI: // M
  2361. case NF_KEY_MMI: // MM
  2362. case NF_KEY_H: // H
  2363. case NF_KEY_HH: // HH
  2364. case NF_KEY_S: // S
  2365. case NF_KEY_SS: // SS
  2366. bTimePart = true;
  2367. sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
  2368. nPos = nPos + sStrArray[i].Len();
  2369. i++;
  2370. break;
  2371. case NF_KEY_M: // M
  2372. case NF_KEY_MM: // MM
  2373. case NF_KEY_MMM: // MMM
  2374. case NF_KEY_MMMM: // MMMM
  2375. case NF_KEY_MMMMM: // MMMMM
  2376. case NF_KEY_Q: // Q
  2377. case NF_KEY_QQ: // QQ
  2378. case NF_KEY_D: // D
  2379. case NF_KEY_DD: // DD
  2380. case NF_KEY_DDD: // DDD
  2381. case NF_KEY_DDDD: // DDDD
  2382. case NF_KEY_YY: // YY
  2383. case NF_KEY_YYYY: // YYYY
  2384. case NF_KEY_NN: // NN
  2385. case NF_KEY_NNN: // NNN
  2386. case NF_KEY_NNNN: // NNNN
  2387. case NF_KEY_WW : // WW
  2388. case NF_KEY_AAA : // AAA
  2389. case NF_KEY_AAAA : // AAAA
  2390. case NF_KEY_EC : // E
  2391. case NF_KEY_EEC : // EE
  2392. case NF_KEY_G : // G
  2393. case NF_KEY_GG : // GG
  2394. case NF_KEY_GGG : // GGG
  2395. case NF_KEY_R : // R
  2396. case NF_KEY_RR : // RR
  2397. bTimePart = false;
  2398. sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT
  2399. nPos = nPos + sStrArray[i].Len();
  2400. i++;
  2401. break;
  2402. case NF_KEY_THAI_T :
  2403. bThaiT = true;
  2404. sStrArray[i] = sKeyword[nTypeArray[i]];
  2405. nPos = nPos + sStrArray[i].Len();
  2406. i++;
  2407. break;
  2408. default: // andere Keywords
  2409. nTypeArray[i] = NF_SYMBOLTYPE_STRING;
  2410. nPos = nPos + sStrArray[i].Len();
  2411. i++;
  2412. break;
  2413. }
  2414. } // of while
  2415. nCntPost = nCounter; // decimals (100th seconds)
  2416. if (bExp)
  2417. nCntExp = 1; // merkt AM/PM
  2418. }
  2419. break; // of NUMBERFORMAT_DATETIME
  2420. default:
  2421. break;
  2422. }
  2423. if (eScannedType == NUMBERFORMAT_SCIENTIFIC &&
  2424. (nCntPre + nCntPost == 0 || nCntExp == 0))
  2425. return nPos;
  2426. else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0))
  2427. return nPos;
  2428. if (bThaiT && !GetNatNumModifier())
  2429. SetNatNumModifier(1);
  2430. if ( bConvertMode )
  2431. { // strings containing keywords of the target locale must be quoted, so
  2432. // the user sees the difference and is able to edit the format string
  2433. for ( i=0; i < nAnzStrings; i++ )
  2434. {
  2435. if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING &&
  2436. sStrArray[i].GetChar(0) != '\"' )
  2437. {
  2438. if ( bConvertSystemToSystem && eScannedType == NUMBERFORMAT_CURRENCY )
  2439. { // don't stringize automatic currency, will be converted
  2440. if ( sStrArray[i] == sOldCurSymbol )
  2441. continue; // for
  2442. // DM might be splitted into D and M
  2443. if ( sStrArray[i].Len() < sOldCurSymbol.Len() &&
  2444. pChrCls->uppercase( sStrArray[i], 0, 1 )[0] ==
  2445. sOldCurString[0] )
  2446. {
  2447. String aTmp( sStrArray[i] );
  2448. sal_uInt16 j = i + 1;
  2449. while ( aTmp.Len() < sOldCurSymbol.Len() &&
  2450. j < nAnzStrings &&
  2451. nTypeArray[j] == NF_SYMBOLTYPE_STRING )
  2452. {
  2453. aTmp += sStrArray[j++];
  2454. }
  2455. if ( pChrCls->uppercase( aTmp ) == sOldCurString )
  2456. {
  2457. sStrArray[i++] = aTmp;
  2458. for ( ; i<j; i++ )
  2459. {
  2460. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  2461. nAnzResStrings--;
  2462. }
  2463. i = j - 1;
  2464. continue; // for
  2465. }
  2466. }
  2467. }
  2468. String& rStr = sStrArray[i];
  2469. xub_StrLen nLen = rStr.Len();
  2470. for ( xub_StrLen j=0; j<nLen; j++ )
  2471. {
  2472. if ( (j == 0 || rStr.GetChar(j-1) != '\\') && GetKeyWord( rStr, j ) )
  2473. {
  2474. rStr.Insert( '\"', 0 );
  2475. rStr += '\"';
  2476. break; // for
  2477. }
  2478. }
  2479. }
  2480. }
  2481. }
  2482. // concatenate strings, remove quotes for output, and rebuild the format string
  2483. rString.Erase();
  2484. i = 0;
  2485. while (i < nAnzStrings)
  2486. {
  2487. switch ( nTypeArray[i] )
  2488. {
  2489. case NF_SYMBOLTYPE_STRING :
  2490. {
  2491. xub_StrLen nStringPos = rString.Len();
  2492. xub_StrLen nArrPos = 0;
  2493. sal_uInt16 iPos = i;
  2494. do
  2495. {
  2496. if (sStrArray[i].Len() == 2 &&
  2497. sStrArray[i].GetChar(0) == '\\')
  2498. {
  2499. // Unescape some simple forms of symbols even in the UI
  2500. // visible string to prevent duplicates that differ
  2501. // only in notation, originating from import.
  2502. // e.g. YYYY-MM-DD and YYYY\-MM\-DD are identical,
  2503. // but 0\ 000 0 and 0 000 0 in a French locale are not.
  2504. sal_Unicode c = sStrArray[i].GetChar(1);
  2505. switch (c)
  2506. {
  2507. case '+':
  2508. case '-':
  2509. rString += c;
  2510. break;
  2511. case ' ':
  2512. case '.':
  2513. case '/':
  2514. if (((eScannedType & NUMBERFORMAT_DATE) == 0)
  2515. && (StringEqualsChar(
  2516. pFormatter->GetNumThousandSep(),
  2517. c) || StringEqualsChar(
  2518. pFormatter->GetNumDecimalSep(),
  2519. c) || (c == ' ' &&
  2520. StringEqualsChar(
  2521. pFormatter->GetNumThousandSep(),
  2522. cNonBreakingSpace))))
  2523. rString += sStrArray[i];
  2524. else if ((eScannedType & NUMBERFORMAT_DATE) &&
  2525. StringEqualsChar(
  2526. pFormatter->GetDateSep(), c))
  2527. rString += sStrArray[i];
  2528. else if ((eScannedType & NUMBERFORMAT_TIME) &&
  2529. (StringEqualsChar( pLoc->getTimeSep(),
  2530. c) ||
  2531. StringEqualsChar(
  2532. pLoc->getTime100SecSep(), c)))
  2533. rString += sStrArray[i];
  2534. else if (eScannedType & NUMBERFORMAT_FRACTION)
  2535. rString += sStrArray[i];
  2536. else
  2537. rString += c;
  2538. break;
  2539. default:
  2540. rString += sStrArray[i];
  2541. }
  2542. }
  2543. else
  2544. rString += sStrArray[i];
  2545. if ( RemoveQuotes( sStrArray[i] ) > 0 )
  2546. { // update currency up to quoted string
  2547. if ( eScannedType == NUMBERFORMAT_CURRENCY )
  2548. { // dM -> DM or DM -> $ in old automatic
  2549. // currency formats, oh my ..., why did we ever
  2550. // introduce them?
  2551. String aTmp( pChrCls->uppercase(
  2552. sStrArray[iPos], nArrPos,
  2553. sStrArray[iPos].Len()-nArrPos ) );
  2554. xub_StrLen nCPos = aTmp.Search( sOldCurString );
  2555. if ( nCPos != STRING_NOTFOUND )
  2556. {
  2557. const String& rCur =
  2558. bConvertMode && bConvertSystemToSystem ?
  2559. GetCurSymbol() : sOldCurSymbol;
  2560. sStrArray[iPos].Replace( nArrPos+nCPos,
  2561. sOldCurString.getLength(), rCur );
  2562. rString.Replace( nStringPos+nCPos,
  2563. sOldCurString.getLength(), rCur );
  2564. }
  2565. nStringPos = rString.Len();
  2566. if ( iPos == i )
  2567. nArrPos = sStrArray[iPos].Len();
  2568. else
  2569. nArrPos = sStrArray[iPos].Len() + sStrArray[i].Len();
  2570. }
  2571. }
  2572. if ( iPos != i )
  2573. {
  2574. sStrArray[iPos] += sStrArray[i];
  2575. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  2576. nAnzResStrings--;
  2577. }
  2578. i++;
  2579. } while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING );
  2580. if ( i < nAnzStrings )
  2581. i--; // enter switch on next symbol again
  2582. if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.Len() )
  2583. { // same as above, since last RemoveQuotes
  2584. String aTmp( pChrCls->uppercase(
  2585. sStrArray[iPos], nArrPos,
  2586. sStrArray[iPos].Len()-nArrPos ) );
  2587. xub_StrLen nCPos = aTmp.Search( sOldCurString );
  2588. if ( nCPos != STRING_NOTFOUND )
  2589. {
  2590. const String& rCur =
  2591. bConvertMode && bConvertSystemToSystem ?
  2592. GetCurSymbol() : sOldCurSymbol;
  2593. sStrArray[iPos].Replace( nArrPos+nCPos,
  2594. sOldCurString.getLength(), rCur );
  2595. rString.Replace( nStringPos+nCPos,
  2596. sOldCurString.getLength(), rCur );
  2597. }
  2598. }
  2599. }
  2600. break;
  2601. case NF_SYMBOLTYPE_CURRENCY :
  2602. {
  2603. rString += sStrArray[i];
  2604. RemoveQuotes( sStrArray[i] );
  2605. }
  2606. break;
  2607. case NF_KEY_THAI_T:
  2608. if (bThaiT && GetNatNumModifier() == 1)
  2609. { // Remove T from format code, will be replaced with a [NatNum1] prefix.
  2610. nTypeArray[i] = NF_SYMBOLTYPE_EMPTY;
  2611. nAnzResStrings--;
  2612. }
  2613. else
  2614. rString += sStrArray[i];
  2615. break;
  2616. case NF_SYMBOLTYPE_EMPTY :
  2617. // nothing
  2618. break;
  2619. default:
  2620. rString += sStrArray[i];
  2621. }
  2622. i++;
  2623. }
  2624. return 0;
  2625. }
  2626. xub_StrLen ImpSvNumberformatScan::RemoveQuotes( String& rStr )
  2627. {
  2628. if ( rStr.Len() > 1 )
  2629. {
  2630. sal_Unicode c = rStr.GetChar(0);
  2631. xub_StrLen n;
  2632. if ( c == '"' && rStr.GetChar( (n = xub_StrLen(rStr.Len()-1)) ) == '"' )
  2633. {
  2634. rStr.Erase(n,1);
  2635. rStr.Erase(0,1);
  2636. return 2;
  2637. }
  2638. else if ( c == '\\' )
  2639. {
  2640. rStr.Erase(0,1);
  2641. return 1;
  2642. }
  2643. }
  2644. return 0;
  2645. }
  2646. xub_StrLen ImpSvNumberformatScan::ScanFormat( String& rString )
  2647. {
  2648. xub_StrLen res = Symbol_Division(rString); //lexikalische Analyse
  2649. if (!res)
  2650. res = ScanType(); // Erkennung des Formattyps
  2651. if (!res)
  2652. res = FinalScan( rString ); // Typabhaengige Endanalyse
  2653. return res; // res = Kontrollposition
  2654. // res = 0 => Format ok
  2655. }
  2656. void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, sal_uInt16 nAnz)
  2657. {
  2658. size_t i,j;
  2659. j = 0;
  2660. i = 0;
  2661. while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS)
  2662. {
  2663. if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY)
  2664. {
  2665. pInfo->sStrArray[i] = sStrArray[j];
  2666. pInfo->nTypeArray[i] = nTypeArray[j];
  2667. i++;
  2668. }
  2669. j++;
  2670. }
  2671. pInfo->eScannedType = eScannedType;
  2672. pInfo->bThousand = bThousand;
  2673. pInfo->nThousand = nThousand;
  2674. pInfo->nCntPre = nCntPre;
  2675. pInfo->nCntPost = nCntPost;
  2676. pInfo->nCntExp = nCntExp;
  2677. }
  2678. /* vim:set shiftwidth=4 softtabstop=4 expandtab: */