From 8661d5579bd19a9e294ddff64bbe817b537dbd46 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Tue, 14 Jun 2022 17:21:18 +0200 Subject: Resolves: tdf#149325 tdf#52602 SvNumberFormatsObj::queryKey try also uppercase ... keywords; that should catch most lower case queries. If there are still remaining mismatches then either implement the bScan thing, or enhance addNew() to not fail on case-different format codes. That could be hit for the `General` keyword, for example. Change-Id: Ic728b8c5e38db76eb791cb305595f84acf7dc867 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135854 Tested-by: Jenkins Reviewed-by: Eike Rathke --- svl/source/numbers/numfmuno.cxx | 51 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'svl') diff --git a/svl/source/numbers/numfmuno.cxx b/svl/source/numbers/numfmuno.cxx index 98ead86e432d..4c3d4abda553 100644 --- a/svl/source/numbers/numfmuno.cxx +++ b/svl/source/numbers/numfmuno.cxx @@ -411,8 +411,55 @@ sal_Int32 SAL_CALL SvNumberFormatsObj::queryKey( const OUString& aFormat, { //! FIXME: Something still needs to happen here ... } - sal_Int32 nRet = pFormatter->GetEntryKey( aFormat, eLang ); - return nRet; + sal_uInt32 nRet = pFormatter->GetEntryKey( aFormat, eLang ); + if (nRet == NUMBERFORMAT_ENTRY_NOT_FOUND) + { + // This seems to be a workaround for what maybe the bScan option was + // intended for? Tokenize the format code? + + // The format string based search is vague and fuzzy, as it is case + // sensitive, but the format string is only half way cased, the + // keywords (except the "General" keyword) are uppercased and literals + // of course are not. Clients using this queryKey() and if not + // successful addNew() may still fail if the result of PutEntry() is + // false because the format actually existed, just with a different + // casing. The only clean way is to just use PutEntry() and ignore the + // duplicate case, which clients can't because the API doesn't provide + // the information. + // Try just another possibilty here, without any guarantee. + + // Use only ASCII upper, because keywords are only those. + // Do not transliterate any quoted literals. + const sal_Int32 nLen = aFormat.getLength(); + OUStringBuffer aBuf(0); + sal_Unicode* p = aBuf.appendUninitialized( nLen + 1); + memcpy( p, aFormat.getStr(), (nLen + 1) * sizeof(sal_Unicode)); // including 0-char + aBuf.setLength( nLen); + assert(p == aBuf.getStr()); + sal_Unicode const * const pStop = p + aBuf.getLength(); + bool bQuoted = false; + for ( ; p < pStop; ++p) + { + if (bQuoted) + { + // Format codes don't have embedded doubled quotes, i.e. "a""b" + // is two literals displayed as `ab`. + if (*p == '"') + bQuoted = false; + } + else if (*p == '"') + bQuoted = true; + else if ('a' <= *p && *p <= 'z') + *p -= 0x20; // upper + else if (*p == '\\') + ++p; // skip escaped next char + // Theoretically that should cater for UTF-32 with + // iterateCodePoints(), but such character would not match any + // of [a-z\"] in its UTF-16 units. + } + nRet = pFormatter->GetEntryKey( aBuf, eLang ); + } + return static_cast(nRet); } sal_Int32 SAL_CALL SvNumberFormatsObj::addNew( const OUString& aFormat, -- cgit