chxavstringutils.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:11k
- /************************************************************************
- * chxavstringutils.cpp
- * --------------------
- *
- * Synopsis:
- * Contains the implementation of the CHXAvStringUtils class. This class is a
- * implements helper static functions to go from our CHXString in helix to
- * Symbian's descriptor classes.
- *
- * Target:
- * Symbian OS
- *
- *
- * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
- *
- *****************************************************************************/
- // Symbian includes...
- #include <aknpopup.h>
- #include <akntitle.h>
- #include <eikenv.h>
- #include <coemain.h>
- #include <stdlib.h>
- #include <charconv.h>
- #include <utf.h>
- // Helix includes...
- #include "hxassert.h"
- #include "hxstring.h"
- //#include "hlxosstr.h"
- #include "hxstring.h"
- #include "hxsym_debug.h"
- #include "hxbuffer.h"
- // Includes from this project...
- #include "chxavmisc.h"
- #include "chxavutil.h"
- #include "chxavcleanupstack.h"
- namespace CHXAvStringUtils
- {
- // assume input comprises single-byte characters and copy out as utf16 (uts-2)
- void CopyRaw(const char* in, TDes& out, TInt count) // XXXLCM move this helpers
- {
- TInt cch = min(count, out.MaxLength());
- out.SetLength(cch);
- for (TInt idx = 0; idx < cch; ++idx)
- {
- out[idx] = (in[idx] & 0xff);
- }
- }
- // return octets needed to encode given unicode character
- TUint CalcUTF8OctetsForConversion(UINT16 ch) // XXXLCM move this helpers
- {
- // utf8 encodes 1-6 bytes per character
- static const unsigned int z_UTF8Bounds[] = {
- 0x80, 0x800, 0x10000, 0x200000, 0x4000000, 0x80000000};
- HX_ASSERT(ch < 0x80000000);
- TUint cchNeeded = 0;
- for(TInt idx = 0; idx < ARRAY_COUNT(z_UTF8Bounds); ++idx)
- {
- if (ch < z_UTF8Bounds[idx])
- {
- cchNeeded = idx + 1;
- break;
- }
- }
- HX_ASSERT(cchNeeded > 0);
- return cchNeeded;
- }
- // return octets needed to encode given unicode string
- TUint CalcUTF8OctetsForConversion(const TDesC& in) // XXXLCM move this helpers
- {
- TUint cchTotal = 0;
- TInt cch = in.Length();
- for (TInt idx = 0; idx < cch; ++idx)
- {
- cchTotal += CalcUTF8OctetsForConversion(in[idx]);
- }
- return cchTotal;
- }
- TInt GetUtf8TrailingOctetCount(char ch)
- {
- HX_ASSERT((ch & 0xc0) == 0xc0); // first char in utf8 multibyte char sequence begins with '11...'
-
- TInt count = 0;
- if ((ch & 0x20) == 0)
- {
- // '110...'
- count = 1;
- }
- else if( (ch & 0x10) == 0)
- {
- // '1110...'
- count = 2;
- }
- else if( (ch & 0x08) == 0)
- {
- // '11110...'
- count = 3;
- }
- else if( (ch & 0x04) == 0)
- {
- // '111110...'
- count = 4;
- }
- else if( (ch & 0x02) == 0)
- {
- // '1111110...'
- count = 5;
- }
- else
- {
- // '1111111...' not a valid utf-8 character
- count = -1;
- }
- return count;
- }
- bool IsValidUtf8(const char* pText, TInt cchText)
- {
- HX_ASSERT(cchText != 0);
- HX_ASSERT(pText);
- bool bIsValid = true;
- TInt idx = 0;
- while(idx < cchText)
- {
- char ch = pText[idx++];
- if( (ch & 0x80) == 0 )
- {
- // plain ascii char (0 - 127) that is also a valid utf8 char
- continue;
- }
- else if( (ch & 0x40) == 0 )
- {
- // first char in multibyte utf8 char sequence never begins with '10...'
- bIsValid = false;
- break;
- }
- else
- {
- TInt trailCount = GetUtf8TrailingOctetCount(ch);
- const TInt k_maxUtf8TrailingOctets = 5;
- HX_ASSERT(trailCount <= k_maxUtf8TrailingOctets);
- if(-1 == trailCount)
- {
- bIsValid = false;
- break;
- }
- if( idx + trailCount > cchText )
- {
- // can't verify this multibyte utf-8 char
- bIsValid = false;
- break;
- }
- // verify that each trailing octet begins with '10' as two most-significant bits
- for(TInt idxTrail = 0; idxTrail < trailCount; ++idxTrail)
- {
- // each trailing octet must begin with '10...'
- ch = pText[idx++];
- if( (ch & 0xc0) != 0x80 )
- {
- bIsValid = false;
- break;
- }
- }
- if( !bIsValid )
- {
- break;
- }
- }
- }
- return bIsValid;
- }
- /*
- * DesToString
- * -----------
- * convert from unicode to utf-8 string
- *
- */
- void
- DesToString(const TDesC& in, CHXString& out)
- {
- out = "";
- TInt cch = in.Length();
- if( cch )
- {
- TInt cchNeeded = CalcUTF8OctetsForConversion(in);
- HBufC8* pbuf = HBufC8::New(cchNeeded);
- if(pbuf)
- {
- TPtr8 ptrOut = pbuf->Des();
- TInt cchUnconverted = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptrOut, in);
- HX_ASSERT(cchUnconverted == 0);
- if(cchUnconverted == 0)
- {
- out = CHXString(reinterpret_cast<const char*>(ptrOut.Ptr()), ptrOut.Length());
- }
- HX_DELETE(pbuf);
- }
- }
- }
- /*
- * StringToDes
- * -----------
- * convert from utf-8 or ansi (single-byte) string to unicode descriptor
- *
- */
- void StringToDes(const CHXString& in, TDes& out)
- {
- if(in.GetLength() > 0)
- {
- // scan the string to see if it looks like utf8; CnvUtfConverter doesn't fail in every case for non utf8 input (e.g., copyright char)
- if( IsValidUtf8(in, in.GetLength()) )
- {
- TPtrC8 from( reinterpret_cast<const TUint8*>(static_cast<const char*>(in)) );
- TInt cchUnconverted = CnvUtfConverter::ConvertToUnicodeFromUtf8(out, from);
- HX_ASSERT(0 == cchUnconverted);
- }
- else
- {
- // assume string is ansi single-byte format
- DPRINTF(SYMP_INFO, ("StringToDes(): input not utf-8? assuming single-byten"));
- CopyRaw(in, out, in.GetLength());
- }
- }
- else
- {
- out.Zero();
- }
- }
- /*
- * StringToHBuf
- * ------------
- * Takes a string and returns the HBufC equivalent.
- *
- */
- HBufC*
- StringToHBuf(const CHXString& s)
- {
- HBufC* buf = HBufC::NewMax(s.GetLength());
- TPtr des = buf->Des();
- StringToDes(s, des);
- return buf;
- }
- CHXString
- DescToString(const TDesC& desc)
- {
- CHXString str;
- DesToString(desc, str);
- return str;
- }
- void
- Replace(TPtr& ptr, char oldChar, char newChar)
- {
- for (TInt idx = 0; idx < ptr.Length(); ++idx)
- {
- if (ptr[idx] == oldChar)
- {
- ptr[idx] = newChar;
- }
- }
- }
- /*
- * AllocTextL
- * ------------------
- * concatenate strings
- *
- */
- ////////////////////////////////////////
- //
- // return one + two + three
- //
- HBufC* AllocTextL(const TDesC& one, const TDesC& two, const TDesC& three)
- {
- HBufC* pNewString = HBufC::NewL(one.Length() + two.Length() + three.Length());
- TPtr ptr = pNewString->Des();
- ptr.Copy(one);
- ptr.Append(two);
- ptr.Append(three);
- return pNewString;
- }
- ////////////////////////////////////////////////////////////
- //
- HBufC*
- AllocTextL(const CHXString& str)
- {
- HBufC* pText = HBufC::NewL(str.GetLength());
- TPtr ptr = pText->Des();
- StringToDes(str, ptr);
- return pText;
- }
- #if defined(DEBUG)
- // for resource text helpers below
- _LIT(KNumericArg, "%d");
- _LIT(KStringArg, "%S");
- _LIT(KRealArg, "%f");
- _LIT(KRealArgPrecision, "%.1f");
- _LIT(KHexArg, "%x");
- #endif
- HBufC* AllocResTextL(TInt resId)
- {
- return CEikonEnv::Static()->AllocReadResourceL(resId);
- }
- //////////////////////////////////////
- // alloc text with TInt arg sprintf'd into text loaded from resId
- //
- HBufC* AllocResFormatTextL(TInt resId, TInt arg)
- {
- HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
- HX_ASSERT(KErrNotFound != pFormatString->Find(KNumericArg));
- AUTO_PUSH_POP_DEL(pFormatString);
- HBufC* pText = HBufC::NewL(pFormatString->Length() + CHXAvUtil::KMaxInt32Chars);
- pText->Des().Format(*pFormatString, arg);
- return pText;
- }
- //////////////////////////////////////
- // alloc text with double arg sprintf'd into text loaded from resId
- //
- HBufC* AllocResFormatTextL(TInt resId, double arg)
- {
- HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
- HX_ASSERT( KErrNotFound != pFormatString->Find(KRealArg) || KErrNotFound != pFormatString->Find(KRealArgPrecision) );
- AUTO_PUSH_POP_DEL(pFormatString);
- HBufC* pText = HBufC::NewL(pFormatString->Length() + CHXAvUtil::KMaxDoubleChars);
- pText->Des().Format(*pFormatString, arg);
- return pText;
- }
- HBufC* AllocResFormatTextL(TInt resId, const TDesC& desc)
- {
- HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
- HX_ASSERT(KErrNotFound != pFormatString->Find(KStringArg));
- AUTO_PUSH_POP_DEL(pFormatString);
- HBufC* pText = HBufC::NewL(pFormatString->Length() + desc.Length());
- pText->Des().Format(*pFormatString, &desc);
- return pText;
- }
-
- HBufC* AllocFormatTextL(const TDesC& formatString, TInt arg)
- {
- HX_ASSERT(KErrNotFound != formatString.Find(KNumericArg));
- const TUint k_cchNumericPart = CHXAvUtil::KMaxInt32Chars * 2; // account for commas, decimals added
- HBufC* pText = HBufC::NewL(formatString.Length() + k_cchNumericPart);
- pText->Des().Format(formatString, arg);
- return pText;
- }
- HBufC* AllocFormatTextHexArgL(const TDesC& formatString, TUint hexArg)
- {
- HX_ASSERT(KErrNotFound != formatString.Find(KHexArg));
- const TUint k_cchNumericPart = CHXAvUtil::KMaxInt32Chars * 2;
- HBufC* pText = HBufC::NewL(formatString.Length() + k_cchNumericPart);
- pText->Des().Format(formatString, hexArg);
- return pText;
- }
- ////////////////////////////////////
- //
- // allocate modified text string if textIn is too large to fit in cxDisplay
- //
- // if pTextOut is NULL upon return, the original text is small enough to fit
- //
- // caller should de-allocate pTextOut
- //
- void
- GetTruncatedDisplayTextL(const TDesC& textIn,
- const CFont* pFont,
- TInt cxDisplay, HBufC*& pTextOut,
- bool bUseEllipsis)
- {
- _LIT(KEllipsisText, "...");
- HX_ASSERT(pFont != 0);
- pTextOut = 0;
- if (pFont->TextWidthInPixels(textIn) > cxDisplay)
- {
- // text is too big to fit in our rect...
- TInt cxEllipsis = pFont->TextWidthInPixels(KEllipsisText);
- if( cxDisplay < cxEllipsis )
- {
- // not enough room for ellipsis
- // NP_ASSERT(false);
- bUseEllipsis = false;
- }
- TInt textInCount = 0;
- TInt totalCount = 0;
- if(bUseEllipsis)
- {
- textInCount = pFont->TextCount(textIn, cxDisplay - cxEllipsis);
- totalCount = textInCount + KEllipsisText().Length();
- }
- else
- {
- textInCount = pFont->TextCount(textIn, cxDisplay);
- totalCount = textInCount;
- }
- pTextOut = HBufC::NewMaxL(totalCount);
- TPtr des = pTextOut->Des();
- // copy clipped text
- des.Copy(textIn.Left(textInCount));
- // get rid of trailing space before ellipsis
- des.TrimRight();
- // add ellipsis
- if( bUseEllipsis )
- {
- des.Append(KEllipsisText);
- }
- }
- }
- } // ns CHXAvStringUtils