diff options
author | Wang Lei <leiw@apache.org> | 2012-10-10 06:08:12 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2013-06-11 12:30:10 +0100 |
commit | 0946de1e2fbf8bd5ad3919429f648359d4464eca (patch) | |
tree | 5d3fa059defeeb3d3216e0f9e15eecd97917405d /sc/source | |
parent | 1691607cc44579bc8193db382d96038177acfc64 (diff) |
Resolves: #i121120 Support RightB(), LeftB(), LenB() and MidB()
Patch by: Zhang Lu
Review by: Wang Lei
(cherry picked from commit 424079cb8348d77e40f7d3291578bdffbe662f34)
Conflicts:
formula/inc/formula/compiler.hrc
formula/inc/formula/opcode.hxx
oox/source/xls/formulabase.cxx
sc/inc/helpids.h
sc/util/hidother.src
sc/util/makefile.mk
Change-Id: Ia04aa69aa2764842507b36ba7cc8c99e99a314e9
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/core/inc/interpre.hxx | 4 | ||||
-rw-r--r-- | sc/source/core/tool/interpr1.cxx | 177 | ||||
-rw-r--r-- | sc/source/core/tool/interpr4.cxx | 4 | ||||
-rw-r--r-- | sc/source/filter/excel/xlformula.cxx | 4 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabase.cxx | 8 | ||||
-rw-r--r-- | sc/source/ui/src/scfuncs.src | 124 |
6 files changed, 317 insertions, 4 deletions
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 81af5a1c7ff2..102b9b017b3b 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -788,6 +788,10 @@ void ScSTEXY(); void ScSlope(); void ScTrend(); void ScInfo(); +void ScLenB(); +void ScRightB(); +void ScLeftB(); +void ScMidB(); static const double fMaxGammaArgument; diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 0ff740c1d289..c4960c5e1194 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -34,6 +34,7 @@ #include <unotools/transliterationwrapper.hxx> #include <rtl/ustring.hxx> #include <rtl/logfile.hxx> +#include <unicode/uchar.h> #include "patattr.hxx" #include "global.hxx" @@ -8620,6 +8621,182 @@ void ScInterpreter::ScLeft() } } +typedef struct { + UBlockCode from; + UBlockCode to; +} UBlockScript; + +static UBlockScript scriptList[] = { + {UBLOCK_HANGUL_JAMO, UBLOCK_HANGUL_JAMO}, + {UBLOCK_CJK_RADICALS_SUPPLEMENT, UBLOCK_HANGUL_SYLLABLES}, + {UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS,UBLOCK_CJK_RADICALS_SUPPLEMENT }, + {UBLOCK_IDEOGRAPHIC_DESCRIPTION_CHARACTERS,UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS}, + {UBLOCK_CJK_COMPATIBILITY_FORMS, UBLOCK_CJK_COMPATIBILITY_FORMS}, + {UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS, UBLOCK_HALFWIDTH_AND_FULLWIDTH_FORMS}, + {UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B, UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT}, + {UBLOCK_CJK_STROKES, UBLOCK_CJK_STROKES} +}; +#define scriptListCount sizeof (scriptList) / sizeof (UBlockScript) +bool SAL_CALL lcl_getScriptClass(sal_uInt32 currentChar) +{ + // for the locale of ja-JP, character U+0x005c and U+0x20ac should be ScriptType::Asian + if( (currentChar == 0x005c || currentChar == 0x20ac) && + (MsLangId::getSystemLanguage() == LANGUAGE_JAPANESE) ) + return true; + sal_uInt16 i; + static sal_Int16 nRet = 0; + UBlockCode block = (UBlockCode)ublock_getCode((sal_uInt32)currentChar); + for ( i = 0; i < scriptListCount; i++) { + if (block <= scriptList[i].to) break; + } + nRet = (i < scriptListCount && block >= scriptList[i].from); + return nRet; +} +bool IsDBCS(sal_Unicode ch) +{ + return lcl_getScriptClass(ch); +} +sal_Int32 getLengthB(String &str) +{ + sal_Int32 index = 0; + sal_Int32 length = 0; + if(0 == str.Len()) + return 0; + while(index < str.Len()){ + if(IsDBCS(str.GetChar(index))) + length += 2; + else + length++; + index++; + } + return length; +} +void ScInterpreter::ScLenB() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScLenB" ); + String aStr( GetString() ); + PushDouble( getLengthB(aStr) ); +} +void lcl_RightB(String &aStr, sal_Int32 n) +{ + if( n < getLengthB(aStr) ) + { + sal_Int32 index = aStr.Len(); + while(index-- >= 0) + { + if(0 == n) + { + aStr.Erase( 0, index + 1); + break; + } + if(-1 == n) + { + aStr.Erase( 0, index + 2 ); + aStr.InsertAscii(" ", 0); + break; + } + if(IsDBCS(aStr.GetChar(index))) + n -= 2; + else + n--; + } + } +} +void ScInterpreter::ScRightB() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScRightB" ); + sal_uInt8 nParamCount = GetByte(); + if ( MustHaveParamCount( nParamCount, 1, 2 ) ) + { + sal_Int32 n; + if (nParamCount == 2) + { + double nVal = ::rtl::math::approxFloor(GetDouble()); + if ( nVal < 0.0 || nVal > STRING_MAXLEN ) + { + PushIllegalArgument(); + return ; + } + else + n = (xub_StrLen) nVal; + } + else + n = 1; + String aStr( GetString() ); + lcl_RightB(aStr, n); + PushString( aStr ); + } +} +void lcl_LeftB(String &aStr, sal_Int32 n) +{ + if( n < getLengthB(aStr) ) + { + sal_Int32 index = -1; + while(index++ < aStr.Len()) + { + if(0 == n) + { + aStr.Erase( index ); + break; + } + if(-1 == n) + { + aStr.Erase( index - 1 ); + aStr.InsertAscii(" "); + break; + } + if(IsDBCS(aStr.GetChar(index))) + n -= 2; + else + n--; + } + } +} +void ScInterpreter::ScLeftB() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScLeftB" ); + sal_uInt8 nParamCount = GetByte(); + if ( MustHaveParamCount( nParamCount, 1, 2 ) ) + { + sal_Int32 n; + if (nParamCount == 2) + { + double nVal = ::rtl::math::approxFloor(GetDouble()); + if ( nVal < 0.0 || nVal > STRING_MAXLEN ) + { + PushIllegalArgument(); + return ; + } + else + n = (xub_StrLen) nVal; + } + else + n = 1; + String aStr( GetString() ); + lcl_LeftB(aStr, n); + PushString( aStr ); + } +} +void ScInterpreter::ScMidB() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "luzhang", "ScInterpreter::ScMidB" ); + if ( MustHaveParamCount( GetByte(), 3 ) ) + { + double fAnz = ::rtl::math::approxFloor(GetDouble()); + double fAnfang = ::rtl::math::approxFloor(GetDouble()); + String rStr( GetString() ); + if (fAnfang < 1.0 || fAnz < 0.0 || fAnfang > double(STRING_MAXLEN) || fAnz > double(STRING_MAXLEN)) + PushIllegalArgument(); + else + { + + lcl_LeftB(rStr, (xub_StrLen)fAnfang + (xub_StrLen)fAnz - 1); + sal_Int32 nCnt = getLengthB(rStr) - (xub_StrLen)fAnfang + 1; + lcl_RightB(rStr, nCnt>0 ? nCnt:0); + PushString(rStr); + } + } +} void ScInterpreter::ScRight() { diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 1f789b96b333..60383f0fa5e2 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4174,6 +4174,10 @@ StackVar ScInterpreter::Interpret() case ocGetPivotData : ScGetPivotData(); break; case ocJis : ScJis(); break; case ocAsc : ScAsc(); break; + case ocLenB : ScLenB(); break; + case ocRightB : ScRightB(); break; + case ocLeftB : ScLeftB(); break; + case ocMidB : ScMidB(); break; case ocUnicode : ScUnicode(); break; case ocUnichar : ScUnichar(); break; case ocBitAnd : ScBitAnd(); break; diff --git a/sc/source/filter/excel/xlformula.cxx b/sc/source/filter/excel/xlformula.cxx index d4bdc8643a11..337b97131c70 100644 --- a/sc/source/filter/excel/xlformula.cxx +++ b/sc/source/filter/excel/xlformula.cxx @@ -203,6 +203,10 @@ static const XclFunctionInfo saFuncTable_2[] = { ocIsLogical, 198, 1, 1, V, { VR }, 0, 0 }, { ocDBCount2, 199, 3, 3, V, { RO, RR }, 0, 0 }, { ocCurrency, 204, 1, 2, V, { VR }, EXC_FUNCFLAG_IMPORTONLY, 0 }, + { ocLeftB, 208, 1, 2, V, { VR }, 0, 0 }, + { ocRightB, 209, 1, 2, V, { VR }, 0, 0 }, + { ocMidB, 210, 3, 3, V, { VR }, 0, 0 }, + { ocLenB, 211, 1, 1, V, { VR }, 0, 0 }, { ocRoundUp, 212, 2, 2, V, { VR }, 0, 0 }, { ocRoundDown, 213, 2, 2, V, { VR }, 0, 0 }, { ocExternal, 255, 1, MX, R, { RO_E, RO }, EXC_FUNCFLAG_IMPORTONLY, 0 } diff --git a/sc/source/filter/oox/formulabase.cxx b/sc/source/filter/oox/formulabase.cxx index 947b785230b6..c7c358ef3a66 100644 --- a/sc/source/filter/oox/formulabase.cxx +++ b/sc/source/filter/oox/formulabase.cxx @@ -439,10 +439,10 @@ static const FunctionData saFuncTableBiff3[] = { 0/*"FIND"*/, "FINDB", 205, 205, 2, 3, V, { VR }, 0 }, { 0/*"SEARCH"*/, "SEARCHB", 206, 206, 2, 3, V, { VR }, 0 }, { 0/*"REPLACE"*/, "REPLACEB", 207, 207, 4, 4, V, { VR }, 0 }, - { 0/*"LEFT"*/, "LEFTB", 208, 208, 1, 2, V, { VR }, 0 }, - { 0/*"RIGHT"*/, "RIGHTB", 209, 209, 1, 2, V, { VR }, 0 }, - { 0/*"MID"*/, "MIDB", 210, 210, 3, 3, V, { VR }, 0 }, - { 0/*"LEN"*/, "LENB", 211, 211, 1, 1, V, { VR }, 0 }, + { "LEFTB", "LEFTB", 208, 208, 1, 2, V, { VR }, 0 }, + { "RIGHTB", "RIGHTB", 209, 209, 1, 2, V, { VR }, 0 }, + { "MIDB", "MIDB", 210, 210, 3, 3, V, { VR }, 0 }, + { "LENB", "LENB", 211, 211, 1, 1, V, { VR }, 0 }, { "ROUNDUP", "ROUNDUP", 212, 212, 2, 2, V, { VR }, 0 }, { "ROUNDDOWN", "ROUNDDOWN", 213, 213, 2, 2, V, { VR }, 0 }, { "ASC", "ASC", 214, 214, 1, 1, V, { VR }, 0 }, diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index e0659020a144..87b9cdd70f8f 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -9608,6 +9608,130 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 Text [ en-US ] = "The integer number of bits the value is to be shifted." ; }; }; + Resource SC_OPCODE_LENB + { + String 1 // Description + { + Text [ en-US ] = "Calculates length of a text string, with DBCS" ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_TEXT; + U2S( HID_FUNC_LENB ); + 1; 0; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "text" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The text in which the length is to be determined." ; + }; + }; + Resource SC_OPCODE_RIGHTB + { + String 1 // Description + { + Text [ en-US ] = "Returns the last character or characters of a text,with DBCS" ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_TEXT; + U2S( HID_FUNC_RIGHTB ); + 2; 0; 1; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "text" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The text in which the end partial words are to be determined." ; + }; + String 4 // Name of Parameter 2 + { + Text [ en-US ] = "number" ; + }; + String 5 // Description of Parameter 2 + { + Text [ en-US ] = "The number of characters for the end text." ; + }; + }; + Resource SC_OPCODE_LEFTB + { + String 1 // Description + { + Text [ en-US ] = "Returns the first character or characters of a text,with DBCS" ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_TEXT; + U2S( HID_FUNC_LEFTB ); + 2; 0; 1; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "text" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The text where the initial partial words are to be determined." ; + }; + String 4 // Name of Parameter 2 + { + Text [ en-US ] = "number" ; + }; + String 5 // Description of Parameter 2 + { + Text [ en-US ] = "The number of characters for the start text." ; + }; + }; + Resource SC_OPCODE_MIDB + { + String 1 // Description + { + Text [ en-US ] = "Returns a partial text string of a text, with DBCS" ; + }; + ExtraData = + { + 0; + ID_FUNCTION_GRP_TEXT; + U2S( HID_FUNC_MIDB ); + 3; 0; 0; 0; + 0; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "text" ; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "The text in which partial words are to be determined." ; + }; + String 4 // Name of Parameter 2 + { + Text [ en-US ] = "start" ; + }; + String 5 // Description of Parameter 2 + { + Text [ en-US ] = "The position from which the part word is to be determined." ; + }; + String 6 // Name of Parameter 3 + { + Text [ en-US ] = "number" ; + }; + String 7 // Description of Parameter 3 + { + Text [ en-US ] = "The number of characters for the text." ; + }; + }; }; #if defined(U2S) |