symport/e32/euser/us_des.cpp
changeset 1 0a7b44b10206
child 2 806186ab5e14
equal deleted inserted replaced
0:c55016431358 1:0a7b44b10206
       
     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 "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-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 	case 'U':
       
   511 	case 'u':
       
   512 lConv:
       
   513 		if (lng)
       
   514 			{
       
   515 			TInt64 uVal64 = 0;
       
   516 			if (aParameterHandler.HandleParameter(&uVal64, sizeof(TInt64), KAlignTInt64)==TParameterHandler::EParameterExtracted)
       
   517 				{
       
   518 				if (selector=='X')
       
   519 					aFormatedText.iBuffer.NumUC(uVal64,radix);
       
   520 				else
       
   521 					aFormatedText.iBuffer.Num(uVal64,radix);
       
   522 				}
       
   523 			}
       
   524 		else
       
   525 			{
       
   526 			if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
       
   527 				{
       
   528 				if (selector=='X')
       
   529 					aFormatedText.iBuffer.NumUC(uVal,radix);
       
   530 				else
       
   531 					aFormatedText.iBuffer.Num(uVal,radix);
       
   532 				}
       
   533 			}
       
   534 		aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   535 		break;
       
   536 	case 'D': // Decimal conversion
       
   537 	case 'd':
       
   538 	case 'I':
       
   539 	case 'i':
       
   540 		if (lng)
       
   541 			{
       
   542 			TInt64 iVal64=0;
       
   543 			if (aParameterHandler.HandleParameter(&iVal64, sizeof(TInt64),KAlignTInt64)==TParameterHandler::EParameterExtracted)
       
   544 				{
       
   545 				aFormatedText.iBuffer.Num(iVal64);
       
   546 				}
       
   547 			}
       
   548 		else
       
   549 			{
       
   550 			TInt iVal=0;
       
   551 			if (aParameterHandler.HandleParameter(&iVal, sizeof(TInt))==TParameterHandler::EParameterExtracted)
       
   552 				{
       
   553 				aFormatedText.iBuffer.Num(iVal);
       
   554 				}
       
   555 			}
       
   556 		aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   557 		break;
       
   558 	case 'P': // Padded conversion
       
   559 	case 'p':
       
   560 		aFormatedText.iTextLength=0;
       
   561 		break;
       
   562 	case 'C':
       
   563 	case 'c': // Ascii character conversion
       
   564 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
       
   565 			{
       
   566 			aFormatedText.iBuffer.Append(uVal);
       
   567 			}
       
   568 		break;
       
   569 	case 'W': // SLONG binary lsb first conversion
       
   570 	case 'M': // SLONG binary msb first conversion
       
   571 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
       
   572 			{
       
   573 			break;
       
   574 			}
       
   575 		aFormatedText.iTextLength=4/XItemSize;
       
   576 		goto doBinary;
       
   577 	case 'w': // SWORD binary lsb first conversion
       
   578 	case 'm': // SWORD binary msb first conversion
       
   579 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
       
   580 			{
       
   581 			break;
       
   582 			}
       
   583 		aFormatedText.iTextLength=2/XItemSize;
       
   584 		//goto doBinary;
       
   585 doBinary:
       
   586 		{
       
   587 		TUint8* pC;
       
   588 		TInt increment;
       
   589 		if (selector=='m' || selector=='M')
       
   590 			{
       
   591 			pC=((TUint8*)(aFormatedText.iText+aFormatedText.iTextLength))-1;
       
   592 			increment=(-1);
       
   593 			}
       
   594 		else
       
   595 			{
       
   596 			pC=(TUint8*)aFormatedText.iText;
       
   597 			increment=1;
       
   598 			}
       
   599 		for (TInt k=aFormatedText.iTextLength*sizeof(*aFormatedText.iText);k>0;--k)
       
   600 			{
       
   601 			*pC=(TUint8)uVal;
       
   602 			pC+=increment;
       
   603 			uVal>>=8;
       
   604 			}
       
   605 		}
       
   606 		break;
       
   607 	case 'F': // TRealX conversion
       
   608 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
       
   609 			{
       
   610 			break;
       
   611 			}
       
   612 		rVal=rValX;
       
   613 		goto doReal;
       
   614 	case 'f': // TReal conversion
       
   615 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
       
   616 			{
       
   617 			break;
       
   618 			}
       
   619 		goto doReal;
       
   620 	case 'E':
       
   621 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
       
   622 			{
       
   623 			break;
       
   624 			}
       
   625 		rVal=rValX;
       
   626 		realFormatType=KRealFormatExponent|KAllowThreeDigitExp; 	// AnnW - changed from EExponent
       
   627 		goto doReal;
       
   628 	case 'e':
       
   629 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
       
   630 			{
       
   631 			break;
       
   632 			}
       
   633 		realFormatType=KRealFormatExponent|KAllowThreeDigitExp; 	// AnnW - changed from EExponent
       
   634 		//goto doReal;
       
   635 doReal:
       
   636 		{
       
   637 		if (precision==KNoPrecision)
       
   638 			precision=KDefaultPrecision;
       
   639 		TRealFormat realFormat(KMaxRealWidth, precision);
       
   640 		realFormat.iType=realFormatType;
       
   641 		aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
       
   642 		if (aFormatedText.iTextLength<0)
       
   643 			{
       
   644 			if (aFormatedText.iTextLength==KErrGeneral)
       
   645 				XPanicker::Panic_BadFormatDescriptor();
       
   646 			else
       
   647 				aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   648 			}
       
   649 		if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
       
   650 			aFormatedText.iWidth=aFormatedText.iTextLength;
       
   651 		}
       
   652 		break;
       
   653 	case 'G':
       
   654 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
       
   655 			{
       
   656 			break;
       
   657 			}
       
   658 		rVal=rValX;
       
   659 		goto doGReal;
       
   660 	case 'g':
       
   661 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
       
   662 			{
       
   663 			break;
       
   664 			}
       
   665 		//goto doGReal;
       
   666 doGReal:
       
   667 		{
       
   668 		if (precision==KNoPrecision)
       
   669 			precision=KDefaultPrecision;
       
   670 
       
   671 		// aFormatedText.iBuffer must be >= KMaxRealWidth
       
   672 		TRealFormat realFormat(KMaxRealWidth, precision);	// Changed from 'width' to KMaxRealWidth
       
   673 		realFormat.iType=KRealFormatGeneral|KAllowThreeDigitExp;	// AnnW - changed from EGeneral
       
   674 		aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
       
   675 		if (aFormatedText.iTextLength<0)
       
   676 			{
       
   677 			// Doesn't fit in given width
       
   678 			realFormat.iWidth=KDefaultRealWidth;
       
   679 			aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
       
   680 			}
       
   681 		if (aFormatedText.iTextLength<0)
       
   682 			{
       
   683 			if (aFormatedText.iTextLength==KErrGeneral)
       
   684 				XPanicker::Panic_BadFormatDescriptor();
       
   685 			else
       
   686 				aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
       
   687 			}
       
   688 		if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
       
   689 			aFormatedText.iWidth=aFormatedText.iTextLength;
       
   690 		}
       
   691 		break;
       
   692 	default: // Not recognized - output % something
       
   693 		XPanicker::Panic_BadFormatDescriptor();
       
   694 		}
       
   695 	// Justify result of conversion
       
   696 	if (aFormatedText.iWidth==KDefaultJustifyWidth)
       
   697 		aFormatedText.iWidth=aFormatedText.iTextLength;
       
   698 	if (aFormatedText.iTextLength>aFormatedText.iWidth)
       
   699 		aFormatedText.iTextLength=aFormatedText.iWidth;
       
   700 	}
       
   701 
       
   702 template <class XDes, class XDesOverflow, class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
       
   703 void DoAppendFormatList(XDes& aThis,const XDesC& aFormat,VA_LIST aList,XDesOverflow* aOverflowHandler)
       
   704 //
       
   705 // Convert the argument list, using the format descriptor.
       
   706 //
       
   707 	{
       
   708 
       
   709 	const TInt overflowLength=aOverflowHandler? aThis.MaxLength(): KMaxTInt;
       
   710 	const TInt originalLength=aThis.Length();
       
   711 	TBool needSecondPass=EFalse;
       
   712 	TParameterManager parameterManager;
       
   713 	XLex format(aFormat);
       
   714 	TInt implicitFormatDirectiveIndex=0;
       
   715 	FOREVER
       
   716 		{
       
   717 		if (format.Eos())
       
   718 			{
       
   719 			break;
       
   720 			}
       
   721 		const TChar character=format.Get();
       
   722 		if (character!='%')
       
   723 			{
       
   724 			if (!needSecondPass)
       
   725 				{
       
   726 				if (aThis.Length()>=overflowLength)
       
   727 					{
       
   728 					aOverflowHandler->Overflow(aThis);
       
   729 					return;
       
   730 					}
       
   731 				aThis.Append(character);
       
   732 				}
       
   733 			}
       
   734 		else if (format.Peek()=='%')
       
   735 			{
       
   736 			if (!needSecondPass)
       
   737 				{
       
   738 				if (aThis.Length()>=overflowLength)
       
   739 					{
       
   740 					aOverflowHandler->Overflow(aThis);
       
   741 					return;
       
   742 					}
       
   743 				aThis.Append(character);
       
   744 				}
       
   745 			format.Inc();
       
   746 			}
       
   747 		else
       
   748 			{
       
   749 			TFormatDirective formatDirective;
       
   750 			TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager, formatDirective);
       
   751 			XFormatedText formatedText;
       
   752 			const TInt error=parameterManager.PrepareToExtractNextParameter(aList);
       
   753 			if (error!=KErrNone)
       
   754 				{
       
   755 				__ASSERT_DEBUG(error==KErrNotReady, Panic(EUnexpectedError2));
       
   756 				needSecondPass=ETrue;
       
   757 				}
       
   758 			HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
       
   759 			parameterManager.AddFormatDirective(formatDirective);
       
   760 			if (!needSecondPass)
       
   761 				{
       
   762 				if ((aThis.Length()+formatedText.iWidth)>overflowLength)
       
   763 					{
       
   764 					aOverflowHandler->Overflow(aThis);
       
   765 					return;
       
   766 					}
       
   767 				aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
       
   768 				}
       
   769 			++implicitFormatDirectiveIndex;
       
   770 			}
       
   771 		}
       
   772 	if (needSecondPass)
       
   773 		{
       
   774 		aThis.SetLength(originalLength);
       
   775 		parameterManager.PrepareToExtractParameters(aList);
       
   776 		format=aFormat;
       
   777 		implicitFormatDirectiveIndex=0;
       
   778 		FOREVER
       
   779 			{
       
   780 			if (format.Eos())
       
   781 				{
       
   782 				break;
       
   783 				}
       
   784 			const TChar character=format.Get();
       
   785 			if (character!='%')
       
   786 				{
       
   787 				if (aThis.Length()>=overflowLength)
       
   788 					{
       
   789 					aOverflowHandler->Overflow(aThis);
       
   790 					return;
       
   791 					}
       
   792 				aThis.Append(character);
       
   793 				}
       
   794 			else if (format.Peek()=='%')
       
   795 				{
       
   796 				if (aThis.Length()>=overflowLength)
       
   797 					{
       
   798 					aOverflowHandler->Overflow(aThis);
       
   799 					return;
       
   800 					}
       
   801 				aThis.Append(character);
       
   802 				format.Inc();
       
   803 				}
       
   804 			else
       
   805 				{
       
   806 				TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager);
       
   807 				XFormatedText formatedText;
       
   808 				HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
       
   809 				if ((aThis.Length()+formatedText.iWidth)>overflowLength)
       
   810 					{
       
   811 					aOverflowHandler->Overflow(aThis);
       
   812 					return;
       
   813 					}
       
   814 				aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
       
   815 				++implicitFormatDirectiveIndex;
       
   816 				}
       
   817 			}
       
   818 		}
       
   819 	}
       
   820 
       
   821 
       
   822 
       
   823 
       
   824 /**
       
   825 Formats and appends text onto the end of this descriptor's data.
       
   826 	
       
   827 The length of this descriptor is incremented to reflect the new content.
       
   828 	
       
   829 The behaviour of this function is the same as
       
   830 AppendFormat(TRefByValue<const TDesC8> aFmt,TDes8Overflow *aOverflowHandler,...).
       
   831 In practice, it is better and easier to use AppendFormat(), passing a variable number of 
       
   832 arguments as required by the format string.
       
   833 	
       
   834 @param aFormat          The descriptor containing the format string.
       
   835 @param aList            A pointer to an argument list.
       
   836 @param aOverflowHandler If supplied, a pointer to the overflow handler.
       
   837 
       
   838 @see TDes8::AppendFormat
       
   839 @see VA_LIST 
       
   840 */
       
   841 EXPORT_C void TDes8::AppendFormatList(const TDesC8 &aFormat,VA_LIST aList,TDes8Overflow *aOverflowHandler)
       
   842 	{
       
   843 
       
   844 	DoAppendFormatList<TDes8, TDes8Overflow, TDesC8, TFormatedText8, TLex8, TPanicker8, sizeof(TUint8)>(*this,aFormat,aList,aOverflowHandler);
       
   845 	}
       
   846 
       
   847 
       
   848 
       
   849 /**
       
   850 Formats and appends text onto the end of this descriptor's data.
       
   851 	
       
   852 The length of this descriptor is incremented to reflect the new content.
       
   853 	
       
   854 The behaviour of this function is the same as
       
   855 AppendFormat(TRefByValue<const TDesC16> aFmt,TDes16Overflow *aOverflowHandler,...).
       
   856 In practice, it is better and easier to use AppendFormat(), passing a variable number of 
       
   857 arguments as required by the format string.
       
   858 	
       
   859 @param aFormat          The descriptor containing the format string.
       
   860 @param aList            A pointer to an argument list.
       
   861 @param aOverflowHandler If supplied, a pointer to the overflow handler.
       
   862 
       
   863 @see TDes16::AppendFormat
       
   864 @see VA_LIST 
       
   865 */
       
   866 EXPORT_C void TDes16::AppendFormatList(const TDesC16 &aFormat,VA_LIST aList,TDes16Overflow *aOverflowHandler)
       
   867 	{
       
   868 
       
   869 	DoAppendFormatList<TDes16, TDes16Overflow, TDesC16, TFormatedText16, TLex16, TPanicker16, sizeof(TUint16)>(*this,aFormat,aList,aOverflowHandler);
       
   870 	}
       
   871