kernel/eka/euser/us_des.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\us_des.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "us_std.h"
       
    19 
       
    20 // Terrible hack. Surely we should use VA_START instead of the below?
       
    21 #if defined(__EABI__) || (defined(__X86__) && defined(__GCC32__))
       
    22 #define EABI_STYLE_VA_LISTS
       
    23 #endif
       
    24 
       
    25 const TInt KNoPrecision=-1;
       
    26 const TInt KDefaultPrecision=6;
       
    27 const TInt KMaxRealWidth=0x20;
       
    28 
       
    29 // TFormatedText8 and TFormatedText16
       
    30 
       
    31 class TFormatedText8
       
    32 	{
       
    33 public:
       
    34 	TBuf8<0x40> iBuffer;
       
    35 	const TUint8* iText;
       
    36 	TInt iTextLength;
       
    37 	TInt iWidth;
       
    38 	TAlign iJustify;
       
    39 	TChar iFill;
       
    40 	};
       
    41 
       
    42 class TFormatedText16
       
    43 	{
       
    44 public:
       
    45 	TBuf16<0x40> iBuffer;
       
    46 	const TUint16* iText;
       
    47 	TInt iTextLength;
       
    48 	TInt iWidth;
       
    49 	TAlign iJustify;
       
    50 	TChar iFill;
       
    51 	};
       
    52 
       
    53 // TPanicker8 and TPanicker16
       
    54 
       
    55 class TPanicker8
       
    56 	{
       
    57 public:
       
    58 	static inline void Panic_BadFormatDescriptor() {Panic(ETDes8BadFormatDescriptor);}
       
    59 	static inline void Panic_BadFormatParams() {Panic(ETDes8BadFormatParams);}
       
    60 	};
       
    61 
       
    62 class TPanicker16
       
    63 	{
       
    64 public:
       
    65 	static inline void Panic_BadFormatDescriptor() {Panic(ETDes16BadFormatDescriptor);}
       
    66 	static inline void Panic_BadFormatParams() {Panic(ETDes16BadFormatParams);}
       
    67 	};
       
    68 
       
    69 // TFormatDirective
       
    70 
       
    71 class TFormatDirective // basically a sort of array of parameters where the size of each parameter is stored (no more than 4 parameters are possible per format-directive) - it also knows whether the format directive it represents has an explicit index, and if so, what that index is
       
    72 	{
       
    73 public:
       
    74 	inline TFormatDirective() :iSizesOfParametersInBytes(0), iFormatDirectiveIndex(EImplicitFormatDirectiveIndex) {}
       
    75 	void AppendParameter(TInt aSizeOfParameterInBytes,TInt aParameterAlignment);
       
    76 	inline void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex) {iFormatDirectiveIndex=aFormatDirectiveIndex;}
       
    77 private:
       
    78 	friend class TParameterManager;
       
    79 private:
       
    80 	enum {EImplicitFormatDirectiveIndex=-1};
       
    81 	enum
       
    82 		{
       
    83 		EShiftToNumberOfParameters=28,
       
    84 		ENumberOfBitsPerParameter=5,
       
    85 		EMaskForSingleParameter=(1<<ENumberOfBitsPerParameter)-1,
       
    86 		EMaskForAlignmentShift=3,
       
    87 		EMaskForParameterSize=EMaskForSingleParameter&~EMaskForAlignmentShift,
       
    88 		EMaximumNumberOfParameters=EShiftToNumberOfParameters/ENumberOfBitsPerParameter
       
    89 		};
       
    90 private: // these functions are used by the TParameterManager class
       
    91 	inline TInt NumberOfParameters() const {return iSizesOfParametersInBytes>>EShiftToNumberOfParameters;}
       
    92 	TInt SizeOfParameter(TInt aIndex) const;
       
    93 	TUint8* CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const;
       
    94 private:
       
    95 	TUint iSizesOfParametersInBytes; // a compactly stored array
       
    96 	TInt iFormatDirectiveIndex;
       
    97 	};
       
    98 
       
    99 void TFormatDirective::AppendParameter(TInt aSizeOfParameterInBytes, TInt aParameterAlignment)
       
   100 	{
       
   101 	const TInt numberOfParameters=NumberOfParameters();
       
   102 	__ASSERT_DEBUG(numberOfParameters<EMaximumNumberOfParameters, Panic(ENumberOfParametersExceedsMaximum));
       
   103 	__ASSERT_DEBUG((aSizeOfParameterInBytes&EMaskForParameterSize)==aSizeOfParameterInBytes, Panic(ESizeOfParameterTooBig));
       
   104 	iSizesOfParametersInBytes+=(1<<EShiftToNumberOfParameters); // increment the count
       
   105 
       
   106 	switch(aParameterAlignment)
       
   107 		{
       
   108 	case 4:
       
   109 		// aSizeOfParameterInBytes |= 0;
       
   110 		break;
       
   111 	case 8:
       
   112 		aSizeOfParameterInBytes |= 1;
       
   113 		break;
       
   114 	default:
       
   115 		__ASSERT_DEBUG(0, Panic(EUnexpectedError3));
       
   116 		}
       
   117 
       
   118 	iSizesOfParametersInBytes|=(aSizeOfParameterInBytes<<(numberOfParameters*ENumberOfBitsPerParameter)); // store aSizeOfParameterInBytes
       
   119 	}
       
   120 
       
   121 TInt TFormatDirective::SizeOfParameter(TInt aIndex) const
       
   122 	{
       
   123 	__ASSERT_DEBUG(aIndex<NumberOfParameters(), Panic(EParameterIndexOutOfRange1));
       
   124 	return (iSizesOfParametersInBytes>>(aIndex*ENumberOfBitsPerParameter))&EMaskForParameterSize;
       
   125 	}
       
   126 
       
   127 TUint8* TFormatDirective::CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const
       
   128 	{
       
   129 	TInt numParams = NumberOfParameters();
       
   130 	__ASSERT_DEBUG(aIndex<=numParams, Panic(EParameterIndexOutOfRange1));
       
   131 	TInt paramInfo = iSizesOfParametersInBytes;
       
   132 	while(numParams--)
       
   133 		{
       
   134 		TInt alignMask = (4<<(paramInfo&EMaskForAlignmentShift))-1;
       
   135 		aDataPtr = (TUint8*)(((TInt)aDataPtr+alignMask)&~alignMask);
       
   136 		if(!aIndex--)
       
   137 			break;
       
   138 		aDataPtr += paramInfo&EMaskForParameterSize;
       
   139 		paramInfo >>= ENumberOfBitsPerParameter;
       
   140 		}
       
   141 	return const_cast<TUint8*>(aDataPtr);
       
   142 	}
       
   143 
       
   144 // TParameterManager
       
   145 
       
   146 class TParameterManager
       
   147 	{
       
   148 public:
       
   149 	TParameterManager();
       
   150 	void AddFormatDirective(const TFormatDirective& aFormatDirective);
       
   151 	TInt PrepareToExtractNextParameter(VA_LIST aList); // returns either KErrNone or KErrNotReady
       
   152 	void PrepareToExtractParameters(VA_LIST aList);
       
   153 	TInt ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective);
       
   154 private:
       
   155 	enum
       
   156 		{
       
   157 		EMaximumNumberOfFormatDirectives=40,
       
   158 		ENumberOfBytesInBitArray=(EMaximumNumberOfFormatDirectives+7)/8
       
   159 		};
       
   160 private:
       
   161 	inline TBool FormatDirectiveIsSet(TInt aIndex) const {return iFormatDirectivesSet[aIndex/8]&(1<<(aIndex%8));}
       
   162 	inline void MarkFormatDirectiveAsSet(TInt aIndex) {iFormatDirectivesSet[aIndex/8]|=(1<<(aIndex%8)); __ASSERT_DEBUG(FormatDirectiveIsSet(aIndex), Panic(EFormatDirectiveAlreadySet1));}
       
   163 private:
       
   164 	TInt iNumberOfFormatDirectives;
       
   165 	TFixedArray<TUint8, ENumberOfBytesInBitArray> iFormatDirectivesSet;
       
   166 	TFixedArray<TFormatDirective, EMaximumNumberOfFormatDirectives> iFormatDirectives;
       
   167 	TFixedArray<const TUint8*, EMaximumNumberOfFormatDirectives> iFormatDirectiveDataPointers;
       
   168 	};
       
   169 
       
   170 TParameterManager::TParameterManager()
       
   171 	:iNumberOfFormatDirectives(0)
       
   172 	{
       
   173 	TInt i;
       
   174 	for (i=0; i<ENumberOfBytesInBitArray; ++i)
       
   175 		{
       
   176 		iFormatDirectivesSet[i]=0;
       
   177 		}
       
   178 	for (i=0; i<EMaximumNumberOfFormatDirectives; ++i)
       
   179 		{
       
   180 		iFormatDirectiveDataPointers[i]=NULL;
       
   181 		}
       
   182 	}
       
   183 
       
   184 void TParameterManager::AddFormatDirective(const TFormatDirective& aFormatDirective)
       
   185 	{
       
   186 	__ASSERT_ALWAYS(iNumberOfFormatDirectives<EMaximumNumberOfFormatDirectives, Panic(ENumberOfFormatDirectivesExceedsMaximum));
       
   187 	const TInt index=(aFormatDirective.iFormatDirectiveIndex>=0)? aFormatDirective.iFormatDirectiveIndex: iNumberOfFormatDirectives;
       
   188 	__ASSERT_ALWAYS(!FormatDirectiveIsSet(index), Panic(EFormatDirectiveAlreadySet2));
       
   189 	MarkFormatDirectiveAsSet(index);
       
   190 	iFormatDirectives[index]=aFormatDirective;
       
   191 	++iNumberOfFormatDirectives;
       
   192 	}
       
   193 
       
   194 TInt TParameterManager::PrepareToExtractNextParameter(VA_LIST aList)
       
   195 	{
       
   196 	if (iNumberOfFormatDirectives==0)
       
   197 		{
       
   198 #ifdef EABI_STYLE_VA_LISTS
       
   199 		// NB under the EABI we are passing va_list (a struct) by value. 
       
   200 		// We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI 
       
   201 		// extends to the name of the field. So I think the 'nasty' cast is likely to be more
       
   202 		// portable.
       
   203 		const TUint8 ** aL = (const TUint8**)&aList;
       
   204 		iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = aL[0];
       
   205 #else
       
   206 		// The horrible cast is there because you can't assume aList is of 'array' type   
       
   207 		iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = (const TUint8*)(*(TInt*)aList);
       
   208 #endif
       
   209 		}
       
   210 	else
       
   211 		{
       
   212 		const TInt previousFormatDirective=iNumberOfFormatDirectives-1;
       
   213 		const TUint8* dataPointer=iFormatDirectiveDataPointers[previousFormatDirective];
       
   214 		if ((dataPointer==NULL) || !FormatDirectiveIsSet(previousFormatDirective))
       
   215 			{
       
   216 			return KErrNotReady;
       
   217 			}
       
   218 		const TFormatDirective& formatDirective=iFormatDirectives[previousFormatDirective];
       
   219 		dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters());
       
   220 		iFormatDirectiveDataPointers[iNumberOfFormatDirectives]=dataPointer;
       
   221 		}
       
   222 	return KErrNone;
       
   223 	}
       
   224 
       
   225 void TParameterManager::PrepareToExtractParameters(VA_LIST aList)
       
   226 	{
       
   227 #ifdef EABI_STYLE_VA_LISTS
       
   228 	// NB under the EABI we are passing va_list (a struct) by value. 
       
   229 	// We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI 
       
   230 	// extends to the name of the field. So I think the 'nasty' cast is likely to be more
       
   231 	// portable.
       
   232 	const TUint8 ** aL = (const TUint8**)&aList;
       
   233 	const TUint8* dataPointer = aL[0];
       
   234 #else
       
   235 	// The horrible cast is there because you can't assume aList is of 'array' type   
       
   236 	const TUint8* dataPointer = (const TUint8*)(*(TInt*)aList);
       
   237 #endif
       
   238 	if (iNumberOfFormatDirectives>0)
       
   239 		{
       
   240 		for (TInt i=0; ; ++i)
       
   241 			{
       
   242 			__ASSERT_ALWAYS(FormatDirectiveIsSet(i), Panic(EFormatDirectiveNotYetSet));
       
   243 			__ASSERT_DEBUG((iFormatDirectiveDataPointers[i]==NULL) || (iFormatDirectiveDataPointers[i]==dataPointer), Panic(EBadFormatDirectiveDataPointer));
       
   244 			iFormatDirectiveDataPointers[i]=dataPointer;
       
   245 			if (i+1>=iNumberOfFormatDirectives)
       
   246 				{
       
   247 				break;
       
   248 				}
       
   249 			const TFormatDirective& formatDirective=iFormatDirectives[i];
       
   250 			dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters());
       
   251 			}
       
   252 		}
       
   253 	}
       
   254 
       
   255 TInt TParameterManager::ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective)
       
   256 	{
       
   257 	__ASSERT_DEBUG(aFormatDirectiveIndex<EMaximumNumberOfFormatDirectives, Panic(EFormatDirectiveIndexOutOfRange));
       
   258 	const TFormatDirective* formatDirective=NULL;
       
   259 	if (aFormatDirectiveIndex<iNumberOfFormatDirectives)
       
   260 		{
       
   261 		if (!FormatDirectiveIsSet(aFormatDirectiveIndex))
       
   262 			{
       
   263 			return KErrNotReady;
       
   264 			}
       
   265 		formatDirective=&iFormatDirectives[aFormatDirectiveIndex];
       
   266 		}
       
   267 	else
       
   268 		{
       
   269 		__ASSERT_DEBUG(aNextFormatDirective!=NULL, Panic(ENotOnFirstPassOfFormatDescriptor1)); // the above condition (aFormatDirectiveIndex>=iNumberOfFormatDirectives) can only be the case on a first pass of the format descriptor, so assert that we're on the first pass
       
   270 		if (aFormatDirectiveIndex>iNumberOfFormatDirectives)
       
   271 			{
       
   272 			return KErrNotReady;
       
   273 			}
       
   274 		formatDirective=aNextFormatDirective;
       
   275 		}
       
   276 	__ASSERT_DEBUG(aSizeOfParameterInBytes==formatDirective->SizeOfParameter(aParameterIndexWithinFormatDirective), Panic(EInconsistentSizeOfParameter));
       
   277 	const TUint8* dataPointer=iFormatDirectiveDataPointers[aFormatDirectiveIndex];
       
   278 	if (dataPointer==NULL)
       
   279 		{
       
   280 		__ASSERT_DEBUG(aNextFormatDirective!=NULL, Panic(ENotOnFirstPassOfFormatDescriptor2)); // the above condition (dataPointer==NULL) can only be the case on a first pass of the format descriptor, so assert that we're on the first pass
       
   281 		return KErrNotReady;
       
   282 		}
       
   283 	__ASSERT_DEBUG(aParameterIndexWithinFormatDirective<formatDirective->NumberOfParameters(), Panic(EParameterIndexOutOfRange2));
       
   284 	dataPointer = formatDirective->CalculateDataPointer(dataPointer,aParameterIndexWithinFormatDirective);
       
   285 	Mem::Copy(aTarget, dataPointer, aSizeOfParameterInBytes);
       
   286 	return KErrNone;
       
   287 	}
       
   288 
       
   289 // TParameterHandler
       
   290 
       
   291 class TParameterHandler
       
   292 	{
       
   293 public:
       
   294 	enum TAction
       
   295 		{
       
   296 		EParameterNotExtracted,
       
   297 		EParameterExtracted
       
   298 		};
       
   299 public:
       
   300 	inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager, TFormatDirective& aFormatDirective) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(&aFormatDirective), iParameterManager(aParameterManager) {} // for the first pass
       
   301 	inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(NULL), iParameterManager(aParameterManager) {} // for the second pass
       
   302 	TAction HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment=4);
       
   303 	void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex);
       
   304 private:
       
   305 	TInt iFormatDirectiveIndex;
       
   306 	TInt iParameterIndex;
       
   307 	TFormatDirective* iFormatDirective;
       
   308 	TParameterManager& iParameterManager;
       
   309 	};
       
   310 
       
   311 TParameterHandler::TAction TParameterHandler::HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment)
       
   312 // Increments iParameterIndex each time it is called.
       
   313 // This is conceptually a sort of virtual function (i.e. it's behaviour depends on the way the object was constructed), although it is not implemented like that.
       
   314 	{
       
   315 	__ASSERT_DEBUG(aTarget!=NULL, Panic(ENullTargetPointer));
       
   316 	__ASSERT_DEBUG(aSizeOfParameterInBytes>=0, Panic(ENegativeSizeOfParameter));
       
   317 	const TUint machineWordAlignmentConstant=sizeof(TUint)-1;
       
   318 	aSizeOfParameterInBytes+=machineWordAlignmentConstant;
       
   319 	aSizeOfParameterInBytes&=~machineWordAlignmentConstant;
       
   320 
       
   321 	if (iFormatDirective!=NULL)
       
   322 		{
       
   323 		iFormatDirective->AppendParameter(aSizeOfParameterInBytes,aParameterAlignment);
       
   324 		}
       
   325 	const TInt error=iParameterManager.ExtractParameter(aTarget, aSizeOfParameterInBytes, iFormatDirectiveIndex, iParameterIndex, iFormatDirective);
       
   326 #if defined(_DEBUG)
       
   327 	if (iFormatDirective==NULL) // if we're on the second pass...
       
   328 		{
       
   329 		__ASSERT_DEBUG(error==KErrNone, Panic(EErrorOnSecondPassOfFormatDescriptor));
       
   330 		}
       
   331 	else
       
   332 		{
       
   333 		__ASSERT_DEBUG(error==KErrNone || error==KErrNotReady, Panic(EUnexpectedError1));
       
   334 		}
       
   335 #endif
       
   336 	++iParameterIndex;
       
   337 	return (error==KErrNone)? EParameterExtracted: EParameterNotExtracted;
       
   338 	}
       
   339 
       
   340 void TParameterHandler::FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex)
       
   341 	{
       
   342 	if (iFormatDirective!=NULL)
       
   343 		{
       
   344 		iFormatDirective->FormatDirectiveHasExplicitIndex(aFormatDirectiveIndex);
       
   345 		}
       
   346 	iFormatDirectiveIndex=aFormatDirectiveIndex;
       
   347 	}
       
   348 
       
   349 template <class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
       
   350 void HandleFormatDirective(TParameterHandler& aParameterHandler, XFormatedText& aFormatedText, XLex& aFmt)
       
   351 //
       
   352 // Handle a single format directive, i.e. sequence starting with a '%', (although the initial '%' will have been consumed by this point).
       
   353 //
       
   354 	{
       
   355 
       
   356 // Determine alignment of various types on the stack. The FOFF approach 
       
   357 // does not work for GCC 3.4.4 on X86 so we use hardcoded constants instead.
       
   358 #if defined(__GCC32__) && defined(__X86__) 
       
   359 	const TInt KAlignTReal = 4;
       
   360 	const TInt KAlignTRealX = 4;
       
   361 	const TInt KAlignTInt64 = 4;
       
   362 #else
       
   363 	struct TReal_align {char c; TReal a;};
       
   364 	const TInt KAlignTReal = _FOFF(TReal_align,a);
       
   365  #ifndef __VC32__ // MSVC generates an internal compiler error with the following code
       
   366 	struct TRealX_align {char c; TRealX a;};
       
   367 	const TInt KAlignTRealX = _FOFF(TRealX_align,a);
       
   368 
       
   369 	struct TInt64_align {char c; TInt64 a;};
       
   370 	const TInt KAlignTInt64 = _FOFF(TInt64_align,a);
       
   371  #else
       
   372 	const TInt KAlignTRealX = 4;	// Hard code value for MSVC
       
   373 	const TInt KAlignTInt64 = 4;	// Hard code value for MSVC
       
   374  #endif
       
   375 #endif
       
   376 
       
   377 	aFormatedText.iJustify=ERight; // Default is justify right
       
   378 	aFormatedText.iFill=KNoChar; // Default fill character is space
       
   379 	// After a % may come +,-,= or space
       
   380 	if (aFmt.Eos())
       
   381 		XPanicker::Panic_BadFormatDescriptor();
       
   382 	TChar c=aFmt.Get();
       
   383 
       
   384 	if (c=='$')
       
   385 		{
       
   386 		TInt formatDirectiveIndex;
       
   387 		if (aFmt.Val(formatDirectiveIndex)!=0)
       
   388 			XPanicker::Panic_BadFormatDescriptor();
       
   389 		aParameterHandler.FormatDirectiveHasExplicitIndex(formatDirectiveIndex-1);
       
   390 		if (aFmt.Get()!='$')
       
   391 			XPanicker::Panic_BadFormatDescriptor();
       
   392 		c=aFmt.Get();
       
   393 		}
       
   394 
       
   395 	switch (c)
       
   396 		{
       
   397 	case ' ':
       
   398 		aFormatedText.iFill=' ';
       
   399 		break;
       
   400 	case '-':
       
   401 		aFormatedText.iJustify=ELeft;
       
   402 		goto getFill;
       
   403 	case '=':
       
   404 		aFormatedText.iJustify=ECenter;
       
   405 		goto getFill;
       
   406 	case '+':
       
   407 getFill:
       
   408 		if (aFmt.Eos())
       
   409 			XPanicker::Panic_BadFormatDescriptor();
       
   410 		if (!aFmt.Peek().IsDigit())
       
   411 			{
       
   412 			aFormatedText.iFill=aFmt.Get(); // assigning aFormatedText.iFill to something other than KNoChar is necessary as the aParameterHandler.HandleParameter call a couple of lines below will not necessarily set its first parameter (i.e. aFormatedText.iFill) - aFormatedText.iFill is tested against KNoChar ten or so lines below
       
   413 			if (aFormatedText.iFill=='*') // If*  take it from the arguments
       
   414 				aParameterHandler.HandleParameter(&aFormatedText.iFill, sizeof(TUint));
       
   415 			}
       
   416 		break;
       
   417 	default:
       
   418 		aFmt.UnGet();
       
   419 		}
       
   420 
       
   421 	aFormatedText.iWidth=KDefaultJustifyWidth; // Default width is whatever the conversion takes
       
   422 	if (aFmt.Peek().IsDigit())
       
   423 		{
       
   424 		// If it starts with 0 and the fill character has not been
       
   425 		// specified then the fill character will be a 0
       
   426 		// For compatibility with standard C libraries
       
   427 		if (aFmt.Peek()=='0' && aFormatedText.iFill==KNoChar)
       
   428 			{
       
   429 			aFormatedText.iFill='0';
       
   430 			aFmt.Inc();
       
   431 			}
       
   432 		if (aFmt.Peek()!='*')
       
   433 			if (aFmt.Val(aFormatedText.iWidth)) // Convert field width value
       
   434 				XPanicker::Panic_BadFormatDescriptor();
       
   435 		}
       
   436 	if (aFmt.Peek()=='*' && aFormatedText.iWidth==KDefaultJustifyWidth) // If a * then get width from arguments
       
   437 		{
       
   438 		aParameterHandler.HandleParameter(&aFormatedText.iWidth, sizeof(TInt));
       
   439 		aFmt.Inc();
       
   440 		}
       
   441 	// Get precision setting if given
       
   442 	TInt precision=KNoPrecision;
       
   443 	if (aFmt.Peek()=='.')
       
   444 		{
       
   445 		aFmt.Inc();
       
   446 		if (aFmt.Peek()=='*')
       
   447 			{
       
   448 			aParameterHandler.HandleParameter(&precision, sizeof(TInt));
       
   449 			aFmt.Inc();
       
   450 			}
       
   451 		else if (aFmt.Val(precision))
       
   452 			XPanicker::Panic_BadFormatDescriptor();
       
   453 		}
       
   454 	if (aFormatedText.iFill==KNoChar) // If still default fill character make it space
       
   455 		aFormatedText.iFill=' ';
       
   456 	if (aFmt.Eos())
       
   457 		XPanicker::Panic_BadFormatDescriptor();
       
   458 	TChar selector;
       
   459 	TBool lng=EFalse;
       
   460 	TCharUC f=aFmt.Peek();
       
   461 	if (f=='L') // If l set selector for longs
       
   462 		{
       
   463 		aFmt.Inc();
       
   464 		lng=ETrue;
       
   465 		}
       
   466 	selector=aFmt.Get(); // Get the selector in upper case
       
   467 	aFormatedText.iText=aFormatedText.iBuffer.Ptr();
       
   468 	aFormatedText.iTextLength=1;
       
   469 	TRadix radix=EDecimal;
       
   470 	TUint uVal=0;
       
   471 	TReal rVal=0;
       
   472 	TRealX rValX=0;
       
   473 	TInt realFormatType=KRealFormatFixed;
       
   474 	switch (selector)
       
   475 		{
       
   476 	case 'S': // String conversion
       
   477 		{
       
   478 		const XDesC* pB;
       
   479 		if (aParameterHandler.HandleParameter(&pB, sizeof(const TAny*))==TParameterHandler::EParameterExtracted)
       
   480 			{
       
   481 			__ASSERT_DEBUG(pB!=0,XPanicker::Panic_BadFormatParams());
       
   482 			aFormatedText.iTextLength=pB->Length();
       
   483 			if (precision!=KNoPrecision && precision<aFormatedText.iTextLength)
       
   484 				aFormatedText.iTextLength=precision;
       
   485 			aFormatedText.iText=pB->Ptr();
       
   486 			}
       
   487 		}
       
   488 		break;
       
   489 	case 's':
       
   490 		if (aParameterHandler.HandleParameter(&aFormatedText.iText, sizeof(const TAny*))==TParameterHandler::EParameterExtracted)
       
   491 			{
       
   492 			__ASSERT_DEBUG(aFormatedText.iText!=0,XPanicker::Panic_BadFormatParams());
       
   493 			if (precision!=KNoPrecision)
       
   494 				aFormatedText.iTextLength=precision;
       
   495 			else
       
   496 				aFormatedText.iTextLength=User::StringLength(aFormatedText.iText);
       
   497 			}
       
   498 		break;
       
   499 	case 'O':
       
   500 	case 'o':
       
   501 		radix=EOctal;
       
   502 		goto lConv;
       
   503 	case 'X':
       
   504 	case 'x':
       
   505 		radix=EHex;
       
   506 		goto lConv;
       
   507 	case 'B': // Binary conversion
       
   508 	case 'b':
       
   509 		radix=EBinary;
       
   510 		// Fall-through to lConv
       
   511 	case 'U':
       
   512 	case 'u':
       
   513 lConv:
       
   514 		if (lng)
       
   515 			{
       
   516 			TInt64 uVal64 = 0;
       
   517 			if (aParameterHandler.HandleParameter(&uVal64, sizeof(TInt64), KAlignTInt64)==TParameterHandler::EParameterExtracted)
       
   518 				{
       
   519 				if (selector=='X')
       
   520 					aFormatedText.iBuffer.NumUC(uVal64,radix);
       
   521 				else
       
   522 					aFormatedText.iBuffer.Num(uVal64,radix);
       
   523 				}
       
   524 			}
       
   525 		else
       
   526 			{
       
   527 			if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
       
   528 				{
       
   529 				if (selector=='X')
       
   530 					aFormatedText.iBuffer.NumUC(uVal,radix);
       
   531 				else
       
   532 					aFormatedText.iBuffer.Num(uVal,radix);
       
   533 				}
       
   534 			}
       
   535 		aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   536 		break;
       
   537 	case 'D': // Decimal conversion
       
   538 	case 'd':
       
   539 	case 'I':
       
   540 	case 'i':
       
   541 		if (lng)
       
   542 			{
       
   543 			TInt64 iVal64=0;
       
   544 			if (aParameterHandler.HandleParameter(&iVal64, sizeof(TInt64),KAlignTInt64)==TParameterHandler::EParameterExtracted)
       
   545 				{
       
   546 				aFormatedText.iBuffer.Num(iVal64);
       
   547 				}
       
   548 			}
       
   549 		else
       
   550 			{
       
   551 			TInt iVal=0;
       
   552 			if (aParameterHandler.HandleParameter(&iVal, sizeof(TInt))==TParameterHandler::EParameterExtracted)
       
   553 				{
       
   554 				aFormatedText.iBuffer.Num(iVal);
       
   555 				}
       
   556 			}
       
   557 		aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   558 		break;
       
   559 	case 'P': // Padded conversion
       
   560 	case 'p':
       
   561 		aFormatedText.iTextLength=0;
       
   562 		break;
       
   563 	case 'C':
       
   564 	case 'c': // Ascii character conversion
       
   565 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
       
   566 			{
       
   567 			aFormatedText.iBuffer.Append(uVal);
       
   568 			}
       
   569 		break;
       
   570 	case 'W': // SLONG binary lsb first conversion
       
   571 	case 'M': // SLONG binary msb first conversion
       
   572 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
       
   573 			{
       
   574 			break;
       
   575 			}
       
   576 		aFormatedText.iTextLength=4/XItemSize;
       
   577 		goto doBinary;
       
   578 	case 'w': // SWORD binary lsb first conversion
       
   579 	case 'm': // SWORD binary msb first conversion
       
   580 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
       
   581 			{
       
   582 			break;
       
   583 			}
       
   584 		aFormatedText.iTextLength=2/XItemSize;
       
   585 		//goto doBinary;
       
   586 doBinary:
       
   587 		{
       
   588 		TUint8* pC;
       
   589 		TInt increment;
       
   590 		if (selector=='m' || selector=='M')
       
   591 			{
       
   592 			pC=((TUint8*)(aFormatedText.iText+aFormatedText.iTextLength))-1;
       
   593 			increment=(-1);
       
   594 			}
       
   595 		else
       
   596 			{
       
   597 			pC=(TUint8*)aFormatedText.iText;
       
   598 			increment=1;
       
   599 			}
       
   600 		for (TInt k=aFormatedText.iTextLength*sizeof(*aFormatedText.iText);k>0;--k)
       
   601 			{
       
   602 			*pC=(TUint8)uVal;
       
   603 			pC+=increment;
       
   604 			uVal>>=8;
       
   605 			}
       
   606 		}
       
   607 		break;
       
   608 	case 'F': // TRealX conversion
       
   609 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
       
   610 			{
       
   611 			break;
       
   612 			}
       
   613 		rVal=rValX;
       
   614 		goto doReal;
       
   615 	case 'f': // TReal conversion
       
   616 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
       
   617 			{
       
   618 			break;
       
   619 			}
       
   620 		goto doReal;
       
   621 	case 'E':
       
   622 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
       
   623 			{
       
   624 			break;
       
   625 			}
       
   626 		rVal=rValX;
       
   627 		realFormatType=KRealFormatExponent|KAllowThreeDigitExp; 	// AnnW - changed from EExponent
       
   628 		goto doReal;
       
   629 	case 'e':
       
   630 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
       
   631 			{
       
   632 			break;
       
   633 			}
       
   634 		realFormatType=KRealFormatExponent|KAllowThreeDigitExp; 	// AnnW - changed from EExponent
       
   635 		//goto doReal;
       
   636 doReal:
       
   637 		{
       
   638 		if (precision==KNoPrecision)
       
   639 			precision=KDefaultPrecision;
       
   640 		TRealFormat realFormat(KMaxRealWidth, precision);
       
   641 		realFormat.iType=realFormatType;
       
   642 		aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
       
   643 		if (aFormatedText.iTextLength<0)
       
   644 			{
       
   645 			if (aFormatedText.iTextLength==KErrGeneral)
       
   646 				XPanicker::Panic_BadFormatDescriptor();
       
   647 			else
       
   648 				aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   649 			}
       
   650 		if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
       
   651 			aFormatedText.iWidth=aFormatedText.iTextLength;
       
   652 		}
       
   653 		break;
       
   654 	case 'G':
       
   655 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
       
   656 			{
       
   657 			break;
       
   658 			}
       
   659 		rVal=rValX;
       
   660 		goto doGReal;
       
   661 	case 'g':
       
   662 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
       
   663 			{
       
   664 			break;
       
   665 			}
       
   666 		//goto doGReal;
       
   667 doGReal:
       
   668 		{
       
   669 		if (precision==KNoPrecision)
       
   670 			precision=KDefaultPrecision;
       
   671 
       
   672 		// aFormatedText.iBuffer must be >= KMaxRealWidth
       
   673 		TRealFormat realFormat(KMaxRealWidth, precision);	// Changed from 'width' to KMaxRealWidth
       
   674 		realFormat.iType=KRealFormatGeneral|KAllowThreeDigitExp;	// AnnW - changed from EGeneral
       
   675 		aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
       
   676 		if (aFormatedText.iTextLength<0)
       
   677 			{
       
   678 			// Doesn't fit in given width
       
   679 			realFormat.iWidth=KDefaultRealWidth;
       
   680 			aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
       
   681 			}
       
   682 		if (aFormatedText.iTextLength<0)
       
   683 			{
       
   684 			if (aFormatedText.iTextLength==KErrGeneral)
       
   685 				XPanicker::Panic_BadFormatDescriptor();
       
   686 			else
       
   687 				aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   688 			}
       
   689 		if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
       
   690 			aFormatedText.iWidth=aFormatedText.iTextLength;
       
   691 		}
       
   692 		break;
       
   693 	default: // Not recognized - output % something
       
   694 		XPanicker::Panic_BadFormatDescriptor();
       
   695 		}
       
   696 	// Justify result of conversion
       
   697 	if (aFormatedText.iWidth==KDefaultJustifyWidth)
       
   698 		aFormatedText.iWidth=aFormatedText.iTextLength;
       
   699 	if (aFormatedText.iTextLength>aFormatedText.iWidth)
       
   700 		aFormatedText.iTextLength=aFormatedText.iWidth;
       
   701 	}
       
   702 
       
   703 template <class XDes, class XDesOverflow, class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
       
   704 void DoAppendFormatList(XDes& aThis,const XDesC& aFormat,VA_LIST aList,XDesOverflow* aOverflowHandler)
       
   705 //
       
   706 // Convert the argument list, using the format descriptor.
       
   707 //
       
   708 	{
       
   709 
       
   710 	const TInt overflowLength=aOverflowHandler? aThis.MaxLength(): KMaxTInt;
       
   711 	const TInt originalLength=aThis.Length();
       
   712 	TBool needSecondPass=EFalse;
       
   713 	TParameterManager parameterManager;
       
   714 	XLex format(aFormat);
       
   715 	TInt implicitFormatDirectiveIndex=0;
       
   716 	FOREVER
       
   717 		{
       
   718 		if (format.Eos())
       
   719 			{
       
   720 			break;
       
   721 			}
       
   722 		const TChar character=format.Get();
       
   723 		if (character!='%')
       
   724 			{
       
   725 			if (!needSecondPass)
       
   726 				{
       
   727 				if (aThis.Length()>=overflowLength)
       
   728 					{
       
   729 					aOverflowHandler->Overflow(aThis);
       
   730 					return;
       
   731 					}
       
   732 				aThis.Append(character);
       
   733 				}
       
   734 			}
       
   735 		else if (format.Peek()=='%')
       
   736 			{
       
   737 			if (!needSecondPass)
       
   738 				{
       
   739 				if (aThis.Length()>=overflowLength)
       
   740 					{
       
   741 					aOverflowHandler->Overflow(aThis);
       
   742 					return;
       
   743 					}
       
   744 				aThis.Append(character);
       
   745 				}
       
   746 			format.Inc();
       
   747 			}
       
   748 		else
       
   749 			{
       
   750 			TFormatDirective formatDirective;
       
   751 			TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager, formatDirective);
       
   752 			XFormatedText formatedText;
       
   753 			const TInt error=parameterManager.PrepareToExtractNextParameter(aList);
       
   754 			if (error!=KErrNone)
       
   755 				{
       
   756 				__ASSERT_DEBUG(error==KErrNotReady, Panic(EUnexpectedError2));
       
   757 				needSecondPass=ETrue;
       
   758 				}
       
   759 			HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
       
   760 			parameterManager.AddFormatDirective(formatDirective);
       
   761 			if (!needSecondPass)
       
   762 				{
       
   763 				if ((aThis.Length()+formatedText.iWidth)>overflowLength)
       
   764 					{
       
   765 					aOverflowHandler->Overflow(aThis);
       
   766 					return;
       
   767 					}
       
   768 				aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
       
   769 				}
       
   770 			++implicitFormatDirectiveIndex;
       
   771 			}
       
   772 		}
       
   773 	if (needSecondPass)
       
   774 		{
       
   775 		aThis.SetLength(originalLength);
       
   776 		parameterManager.PrepareToExtractParameters(aList);
       
   777 		format=aFormat;
       
   778 		implicitFormatDirectiveIndex=0;
       
   779 		FOREVER
       
   780 			{
       
   781 			if (format.Eos())
       
   782 				{
       
   783 				break;
       
   784 				}
       
   785 			const TChar character=format.Get();
       
   786 			if (character!='%')
       
   787 				{
       
   788 				if (aThis.Length()>=overflowLength)
       
   789 					{
       
   790 					aOverflowHandler->Overflow(aThis);
       
   791 					return;
       
   792 					}
       
   793 				aThis.Append(character);
       
   794 				}
       
   795 			else if (format.Peek()=='%')
       
   796 				{
       
   797 				if (aThis.Length()>=overflowLength)
       
   798 					{
       
   799 					aOverflowHandler->Overflow(aThis);
       
   800 					return;
       
   801 					}
       
   802 				aThis.Append(character);
       
   803 				format.Inc();
       
   804 				}
       
   805 			else
       
   806 				{
       
   807 				TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager);
       
   808 				XFormatedText formatedText;
       
   809 				HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
       
   810 				if ((aThis.Length()+formatedText.iWidth)>overflowLength)
       
   811 					{
       
   812 					aOverflowHandler->Overflow(aThis);
       
   813 					return;
       
   814 					}
       
   815 				aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
       
   816 				++implicitFormatDirectiveIndex;
       
   817 				}
       
   818 			}
       
   819 		}
       
   820 	}
       
   821 
       
   822 
       
   823 
       
   824 
       
   825 /**
       
   826 Formats and appends text onto the end of this descriptor's data.
       
   827 	
       
   828 The length of this descriptor is incremented to reflect the new content.
       
   829 	
       
   830 The behaviour of this function is the same as
       
   831 AppendFormat(TRefByValue<const TDesC8> aFmt,TDes8Overflow *aOverflowHandler,...).
       
   832 In practice, it is better and easier to use AppendFormat(), passing a variable number of 
       
   833 arguments as required by the format string.
       
   834 	
       
   835 @param aFormat          The descriptor containing the format string.
       
   836 @param aList            A pointer to an argument list.
       
   837 @param aOverflowHandler If supplied, a pointer to the overflow handler.
       
   838 
       
   839 @see TDes8::AppendFormat
       
   840 @see VA_LIST 
       
   841 */
       
   842 EXPORT_C void TDes8::AppendFormatList(const TDesC8 &aFormat,VA_LIST aList,TDes8Overflow *aOverflowHandler)
       
   843 	{
       
   844 
       
   845 	DoAppendFormatList<TDes8, TDes8Overflow, TDesC8, TFormatedText8, TLex8, TPanicker8, sizeof(TUint8)>(*this,aFormat,aList,aOverflowHandler);
       
   846 	}
       
   847 
       
   848 
       
   849 
       
   850 /**
       
   851 Formats and appends text onto the end of this descriptor's data.
       
   852 	
       
   853 The length of this descriptor is incremented to reflect the new content.
       
   854 	
       
   855 The behaviour of this function is the same as
       
   856 AppendFormat(TRefByValue<const TDesC16> aFmt,TDes16Overflow *aOverflowHandler,...).
       
   857 In practice, it is better and easier to use AppendFormat(), passing a variable number of 
       
   858 arguments as required by the format string.
       
   859 	
       
   860 @param aFormat          The descriptor containing the format string.
       
   861 @param aList            A pointer to an argument list.
       
   862 @param aOverflowHandler If supplied, a pointer to the overflow handler.
       
   863 
       
   864 @see TDes16::AppendFormat
       
   865 @see VA_LIST 
       
   866 */
       
   867 EXPORT_C void TDes16::AppendFormatList(const TDesC16 &aFormat,VA_LIST aList,TDes16Overflow *aOverflowHandler)
       
   868 	{
       
   869 
       
   870 	DoAppendFormatList<TDes16, TDes16Overflow, TDesC16, TFormatedText16, TLex16, TPanicker16, sizeof(TUint16)>(*this,aFormat,aList,aOverflowHandler);
       
   871 	}
       
   872