chxavstringutils.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:11k
源码类别:

Symbian

开发平台:

C/C++

  1. /************************************************************************
  2.  * chxavstringutils.cpp
  3.  * --------------------
  4.  *
  5.  * Synopsis:
  6.  * Contains the implementation of the CHXAvStringUtils class.  This class is a 
  7.  * implements helper static functions to go from our CHXString in helix to
  8.  * Symbian's descriptor classes.
  9.  *
  10.  * Target:
  11.  * Symbian OS
  12.  *
  13.  *
  14.  * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
  15.  *
  16.  *****************************************************************************/
  17. // Symbian includes...
  18. #include <aknpopup.h>
  19. #include <akntitle.h>
  20. #include <eikenv.h>
  21. #include <coemain.h>
  22. #include <stdlib.h>
  23. #include <charconv.h>
  24. #include <utf.h>
  25. // Helix includes...
  26. #include "hxassert.h"
  27. #include "hxstring.h"
  28. //#include "hlxosstr.h"
  29. #include "hxstring.h"
  30. #include "hxsym_debug.h"
  31. #include "hxbuffer.h"
  32. // Includes from this project...
  33. #include "chxavmisc.h"
  34. #include "chxavutil.h"
  35. #include "chxavcleanupstack.h"
  36. namespace CHXAvStringUtils
  37. {
  38. // assume input comprises single-byte characters and copy out as utf16 (uts-2)
  39. void CopyRaw(const char* in, TDes& out, TInt count) // XXXLCM move this helpers
  40. {
  41.     TInt cch = min(count, out.MaxLength());
  42.     out.SetLength(cch);
  43.     for (TInt  idx = 0; idx < cch; ++idx)
  44.     {
  45. out[idx] = (in[idx] & 0xff);
  46.     }
  47. }
  48. // return octets needed to encode given unicode character
  49. TUint CalcUTF8OctetsForConversion(UINT16 ch) // XXXLCM move this helpers
  50. {
  51.     // utf8 encodes 1-6 bytes per character
  52.     static const unsigned int z_UTF8Bounds[] = {
  53.     0x80, 0x800, 0x10000, 0x200000, 0x4000000, 0x80000000};
  54.     HX_ASSERT(ch < 0x80000000);
  55.     TUint cchNeeded = 0;
  56.     for(TInt idx = 0; idx < ARRAY_COUNT(z_UTF8Bounds); ++idx)
  57.     {
  58. if (ch < z_UTF8Bounds[idx])
  59. {
  60.     cchNeeded = idx + 1;
  61.     break;
  62.         }
  63.     }
  64.     HX_ASSERT(cchNeeded > 0);
  65.     return cchNeeded;
  66. }
  67. // return octets needed to encode given unicode string
  68. TUint CalcUTF8OctetsForConversion(const TDesC& in) // XXXLCM move this helpers
  69. {
  70.     TUint cchTotal = 0;
  71.     TInt cch = in.Length();
  72.     for (TInt  idx = 0; idx < cch; ++idx)
  73.     {
  74.         cchTotal += CalcUTF8OctetsForConversion(in[idx]);
  75.     }
  76.     return cchTotal;
  77. }
  78. TInt GetUtf8TrailingOctetCount(char ch)
  79. {
  80.     HX_ASSERT((ch & 0xc0) == 0xc0); // first char in utf8 multibyte char sequence begins with '11...'
  81.     
  82.     TInt count = 0;
  83.     if ((ch & 0x20) == 0)
  84.     {   
  85.         // '110...'
  86.         count = 1;
  87.     }
  88.     else if( (ch & 0x10) == 0)
  89.     {
  90.         // '1110...'
  91.         count = 2;
  92.     }
  93.     else if( (ch & 0x08) == 0)
  94.     {
  95.         // '11110...'
  96.         count = 3;
  97.     }
  98.     else if( (ch & 0x04) == 0)
  99.     {
  100.         // '111110...'
  101.         count = 4;
  102.     }
  103.     else if( (ch & 0x02) == 0)
  104.     {
  105.         // '1111110...'
  106.         count = 5;
  107.     }
  108.     else
  109.     {
  110.         // '1111111...' not a valid utf-8 character
  111.         count = -1;
  112.     }
  113.     return count;
  114. }
  115. bool IsValidUtf8(const char* pText, TInt cchText)
  116.     HX_ASSERT(cchText != 0);
  117.     HX_ASSERT(pText);
  118.     bool bIsValid = true;
  119.     TInt idx = 0;
  120.     while(idx < cchText)
  121.     {
  122.         char ch = pText[idx++];
  123.         if( (ch & 0x80) == 0 )
  124.         {
  125.             // plain ascii char (0 - 127) that is also a valid utf8 char
  126.             continue;
  127.         }
  128.         else if( (ch & 0x40) == 0 )
  129.         {
  130.             // first char in multibyte utf8 char sequence never begins with '10...'
  131.             bIsValid = false;
  132.             break;
  133.         }
  134.         else
  135.         {
  136.             TInt trailCount = GetUtf8TrailingOctetCount(ch);
  137.             const TInt k_maxUtf8TrailingOctets = 5;
  138.             HX_ASSERT(trailCount <= k_maxUtf8TrailingOctets);
  139.             if(-1 == trailCount)
  140.             {
  141.                 bIsValid = false;
  142.                 break;
  143.             }
  144.             if( idx + trailCount > cchText )
  145.             {
  146.                 // can't verify this multibyte utf-8 char
  147.                 bIsValid = false;
  148.                 break;
  149.             }
  150.             // verify that each trailing octet begins with '10' as two most-significant bits
  151.             for(TInt idxTrail = 0; idxTrail < trailCount; ++idxTrail)
  152.             {
  153.                 // each trailing octet must begin with '10...'
  154.                 ch = pText[idx++];
  155.                 if( (ch & 0xc0) != 0x80 )
  156.                 {
  157.                     bIsValid = false;
  158.                     break;
  159.                 }
  160.             }
  161.             if( !bIsValid )
  162.             {
  163.                 break;
  164.             }
  165.         }
  166.     }
  167.     return bIsValid;
  168. }
  169. /*
  170.  * DesToString
  171.  * -----------
  172.  * convert from unicode to utf-8 string
  173.  *
  174.  */
  175. void
  176. DesToString(const TDesC& in, CHXString& out)
  177. {
  178.     out = "";
  179.     TInt cch = in.Length();
  180.     if( cch )
  181.     {
  182.         TInt cchNeeded = CalcUTF8OctetsForConversion(in);
  183.         HBufC8* pbuf = HBufC8::New(cchNeeded);
  184.         if(pbuf)
  185.         {
  186.             TPtr8 ptrOut = pbuf->Des();
  187.             TInt cchUnconverted = CnvUtfConverter::ConvertFromUnicodeToUtf8(ptrOut, in);
  188.             HX_ASSERT(cchUnconverted == 0);
  189.             if(cchUnconverted == 0)
  190.             {
  191.                 out = CHXString(reinterpret_cast<const char*>(ptrOut.Ptr()), ptrOut.Length());
  192.             }
  193.             HX_DELETE(pbuf);
  194.         }
  195.     }
  196. }
  197. /*
  198.  * StringToDes
  199.  * -----------
  200.  * convert from utf-8 or ansi (single-byte) string to unicode descriptor
  201.  *
  202.  */
  203. void StringToDes(const CHXString& in, TDes& out)
  204. {
  205.     if(in.GetLength() > 0)
  206.     {
  207.         // 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)
  208.         if( IsValidUtf8(in, in.GetLength()) )
  209.         {
  210.             TPtrC8 from( reinterpret_cast<const TUint8*>(static_cast<const char*>(in)) );
  211.             TInt cchUnconverted = CnvUtfConverter::ConvertToUnicodeFromUtf8(out, from);
  212.             HX_ASSERT(0 == cchUnconverted);
  213.         }
  214.         else
  215.         {
  216.             // assume string is ansi single-byte format
  217.             DPRINTF(SYMP_INFO, ("StringToDes(): input not utf-8? assuming single-byten"));
  218.             CopyRaw(in, out, in.GetLength());
  219.         }
  220.     }
  221.     else
  222.     {
  223.         out.Zero();
  224.     }
  225. }
  226. /*
  227.  * StringToHBuf
  228.  * ------------
  229.  * Takes a string and returns the HBufC equivalent.
  230.  *
  231.  */
  232. HBufC* 
  233. StringToHBuf(const CHXString& s)
  234. {
  235.     HBufC* buf = HBufC::NewMax(s.GetLength());
  236.     TPtr des  = buf->Des();
  237.     StringToDes(s, des);
  238.     return buf;
  239. }
  240. CHXString
  241. DescToString(const TDesC& desc)
  242. {
  243.     CHXString str;
  244.     DesToString(desc, str);
  245.     return str;
  246. }
  247. void 
  248. Replace(TPtr& ptr, char oldChar, char newChar)
  249. {
  250.     for (TInt idx = 0; idx < ptr.Length(); ++idx)
  251.     {
  252. if (ptr[idx] == oldChar)
  253. {
  254.     ptr[idx] = newChar;
  255. }
  256.     }
  257. }
  258. /*
  259.  * AllocTextL
  260.  * ------------------
  261.  * concatenate strings
  262.  *
  263.  */
  264. ////////////////////////////////////////
  265. //
  266. // return one + two + three
  267. //
  268. HBufC* AllocTextL(const TDesC& one, const TDesC& two, const TDesC& three)
  269. {
  270.     HBufC* pNewString = HBufC::NewL(one.Length() + two.Length() + three.Length());
  271.     TPtr ptr = pNewString->Des();
  272.     ptr.Copy(one);
  273.     ptr.Append(two);
  274.     ptr.Append(three);
  275.     return pNewString;
  276. }
  277. ////////////////////////////////////////////////////////////
  278. //
  279. HBufC* 
  280. AllocTextL(const CHXString& str)
  281. {
  282.     HBufC* pText = HBufC::NewL(str.GetLength());
  283.     TPtr ptr = pText->Des();
  284.     StringToDes(str, ptr);
  285.     return pText;
  286. }
  287. #if defined(DEBUG)
  288. // for resource text helpers below
  289. _LIT(KNumericArg, "%d");
  290. _LIT(KStringArg, "%S");
  291. _LIT(KRealArg, "%f");
  292. _LIT(KRealArgPrecision, "%.1f");
  293. _LIT(KHexArg, "%x");
  294. #endif
  295. HBufC* AllocResTextL(TInt resId)
  296. {   
  297.     return CEikonEnv::Static()->AllocReadResourceL(resId);
  298. }
  299. //////////////////////////////////////
  300. // alloc text with TInt arg sprintf'd into text loaded from resId
  301. //
  302. HBufC* AllocResFormatTextL(TInt resId, TInt arg)
  303. {
  304.     HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
  305.     HX_ASSERT(KErrNotFound != pFormatString->Find(KNumericArg));
  306.     AUTO_PUSH_POP_DEL(pFormatString);
  307.     HBufC* pText = HBufC::NewL(pFormatString->Length() + CHXAvUtil::KMaxInt32Chars);
  308.     pText->Des().Format(*pFormatString, arg);
  309.     return pText;
  310. }
  311. //////////////////////////////////////
  312. // alloc text with double arg sprintf'd into text loaded from resId
  313. //
  314. HBufC* AllocResFormatTextL(TInt resId, double arg)
  315. {
  316.     HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
  317.     HX_ASSERT( KErrNotFound != pFormatString->Find(KRealArg) || KErrNotFound != pFormatString->Find(KRealArgPrecision) );
  318.     AUTO_PUSH_POP_DEL(pFormatString);
  319.     HBufC* pText = HBufC::NewL(pFormatString->Length() + CHXAvUtil::KMaxDoubleChars);
  320.     pText->Des().Format(*pFormatString, arg);
  321.     return pText;
  322. }
  323. HBufC* AllocResFormatTextL(TInt resId, const TDesC& desc)
  324. {
  325.     HBufC* pFormatString = CEikonEnv::Static()->AllocReadResourceL(resId);
  326.     HX_ASSERT(KErrNotFound != pFormatString->Find(KStringArg));
  327.     AUTO_PUSH_POP_DEL(pFormatString);
  328.     HBufC* pText = HBufC::NewL(pFormatString->Length() + desc.Length());
  329.     pText->Des().Format(*pFormatString, &desc);
  330.     return pText;
  331. }
  332.  
  333. HBufC* AllocFormatTextL(const TDesC& formatString, TInt arg)
  334. {
  335.     HX_ASSERT(KErrNotFound != formatString.Find(KNumericArg));
  336.     const TUint k_cchNumericPart = CHXAvUtil::KMaxInt32Chars * 2; // account for commas, decimals added
  337.     HBufC* pText = HBufC::NewL(formatString.Length() + k_cchNumericPart);
  338.     pText->Des().Format(formatString, arg);
  339.     return pText;
  340. }
  341. HBufC* AllocFormatTextHexArgL(const TDesC& formatString, TUint hexArg)
  342. {
  343.     HX_ASSERT(KErrNotFound != formatString.Find(KHexArg));
  344.     const TUint k_cchNumericPart = CHXAvUtil::KMaxInt32Chars * 2;
  345.     HBufC* pText = HBufC::NewL(formatString.Length() + k_cchNumericPart);
  346.     pText->Des().Format(formatString, hexArg);
  347.     return pText;
  348. }
  349. ////////////////////////////////////
  350. //
  351. // allocate modified text string if textIn is too large to fit in cxDisplay
  352. //
  353. // if pTextOut is NULL upon return, the original text is small enough to fit
  354. //
  355. // caller should de-allocate pTextOut
  356. //
  357. void 
  358. GetTruncatedDisplayTextL(const TDesC& textIn, 
  359.       const CFont* pFont,
  360. TInt cxDisplay, HBufC*& pTextOut, 
  361. bool bUseEllipsis)
  362. {
  363.     _LIT(KEllipsisText, "...");
  364.     HX_ASSERT(pFont != 0);
  365.     pTextOut = 0; 
  366.     if (pFont->TextWidthInPixels(textIn) > cxDisplay)
  367.     {
  368. // text is too big to fit in our rect...
  369. TInt cxEllipsis = pFont->TextWidthInPixels(KEllipsisText);
  370. if( cxDisplay < cxEllipsis )
  371. {
  372.     // not enough room for ellipsis
  373.     // NP_ASSERT(false);
  374.     bUseEllipsis = false;
  375. }
  376.         TInt textInCount = 0;
  377. TInt totalCount = 0;
  378. if(bUseEllipsis)
  379. {
  380.     textInCount = pFont->TextCount(textIn, cxDisplay - cxEllipsis);
  381.     totalCount = textInCount + KEllipsisText().Length();
  382. }
  383. else
  384. {
  385.     textInCount = pFont->TextCount(textIn, cxDisplay);
  386.     totalCount = textInCount;
  387. }
  388. pTextOut = HBufC::NewMaxL(totalCount);
  389. TPtr des = pTextOut->Des();
  390. // copy clipped text
  391. des.Copy(textIn.Left(textInCount));
  392. // get rid of trailing space before ellipsis
  393. des.TrimRight();
  394. // add ellipsis
  395. if( bUseEllipsis )
  396. {
  397.     des.Append(KEllipsisText);
  398. }
  399.     }
  400. }
  401. } // ns CHXAvStringUtils