fep/aknfep/src/AknFepInlineTextDecorator.cpp
changeset 0 eb1f2e154e89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fep/aknfep/src/AknFepInlineTextDecorator.cpp	Tue Feb 02 01:02:04 2010 +0200
@@ -0,0 +1,229 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0""
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:           
+*
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+// CAknFepInlineTextDecorator class
+//
+#include <aknenv.h>
+
+#include "AknFepInlineTextDecorator.h"
+#include "AknFepManager.h"
+
+#ifdef _DEBUG
+#include "AknFepPanic.h"
+#endif
+
+void CAknFepInlineTextDecorator::DecorateInlineText(
+	const TDesC& aInlineText,
+	TDes& aDecoratedText,
+	TInt& aPositionOfInsertionPointInInlineText,
+	TChar aPreviousCharacter,
+	TBool aRTLParagraph,
+    TBool aInputDirectionIsRTL)
+	{
+	DecorateNeutralCharacters(aInlineText, aDecoratedText, aPositionOfInsertionPointInInlineText, 
+                              aPreviousCharacter, aRTLParagraph, aInputDirectionIsRTL);
+	}
+
+/**
+* This routine performs a consolidation of directional markers in the region around text being committed.
+* It returns EFalse if no change has been made to the buffer.
+*/
+TBool CAknFepInlineTextDecorator::ResolveDecoratedText(
+	TDes& aDecoratedTextPlusSurroundings,
+	TCursorSelection aDecoratedTextSpan)
+	{
+	TBool needsResolving(EFalse); // Return value
+	
+    // Note that this is a copy of a part of the buffer and that aNewTextSpan is relative to this
+    // new buffer, not the whole text buffer.
+    // aNewTextSpan must fit within the descriptor; that is from 0 to length-1
+    // But remember that span is a span; indices refer to positions between characters. 0 is position just before 0
+    // 1 is a position between 0 and character 1.  
+    __ASSERT_DEBUG(aDecoratedTextSpan.LowerPos() >= 0, 
+                   AknFepPanic(EAknFepPanicCharPosOutOfRange) );
+    __ASSERT_DEBUG(aDecoratedTextSpan.HigherPos() <= aDecoratedTextPlusSurroundings.Length(), 
+                   AknFepPanic(EAknFepPanicCharPosOutOfRange) );
+    
+    // Examine the decorated text for real content
+    TBool cont = EFalse;
+	TInt ii = 0;
+	for (ii = aDecoratedTextSpan.LowerPos(); ii < aDecoratedTextSpan.HigherPos(); ii++)
+		{
+		if (!CharacterIsDirectionalMarker(aDecoratedTextPlusSurroundings[ii]))
+			cont = ETrue;
+		}
+	// if all we have entered are directional markers we want
+	// to keep them so do nothing and return
+	if (!cont)
+		return needsResolving; // Uses initialized value of return value. Please maintain.
+
+	ii = 0;
+	while (ii < aDecoratedTextPlusSurroundings.Length())
+		{
+		TChar prevCh = ENullChar;
+		if (ii > 0)
+			prevCh = aDecoratedTextPlusSurroundings[ii-1];
+		TChar ch = aDecoratedTextPlusSurroundings[ii];
+		TChar nextCh = ENullChar;
+		if (ii <  aDecoratedTextPlusSurroundings.Length()-1)
+			nextCh = aDecoratedTextPlusSurroundings[ii+1];
+
+		if (CharacterIsDirectionalMarker(ch))
+			{
+			// Remove a marker if :
+			//
+			// 1. previous character is strong and has the same directionality
+			// 2. next character is a marker of the same type (remove both)
+			// 3. next character is strong and has the same directionality
+			//
+			if (CharactersHaveSameStrongDirection(ch, prevCh))
+				{
+				aDecoratedTextPlusSurroundings.Delete(ii, ESingleCharacter);
+				ii--;
+				needsResolving = ETrue;
+				}
+			else if (CharacterIsDirectionalMarker(nextCh) && CharactersHaveSameStrongDirection(ch, nextCh))
+				{
+				aDecoratedTextPlusSurroundings.Delete(ii, ETwoCharacters);
+				ii--;
+				needsResolving = ETrue;
+				}
+			else if (CharactersHaveSameStrongDirection(ch, nextCh))
+				{
+				aDecoratedTextPlusSurroundings.Delete(ii, ESingleCharacter);
+				ii--;
+				needsResolving = ETrue;
+				}
+			}
+		ii++;
+		}
+    return needsResolving;
+	}
+
+
+TBool CAknFepInlineTextDecorator::CharacterIsDirectionalMarker(TChar aChar)
+	{
+	return (aChar == ELeftToRightMark || aChar == ERightToLeftMark);
+	}
+
+TBool CAknFepInlineTextDecorator::CharacterIsStrongLeftToRight(TChar aChar)
+	{
+	return (aChar.GetBdCategory() == TChar::ELeftToRight ||
+			   aChar == ELeftToRightMark);
+	}
+
+TBool CAknFepInlineTextDecorator::CharacterIsStrongRightToLeft(TChar aChar)
+	{
+	return ((aChar.GetBdCategory() == TChar::ERightToLeft) || 
+			(aChar.GetBdCategory() == TChar::ERightToLeftArabic) ||
+			aChar == ERightToLeftMark);
+	}
+
+TBool CAknFepInlineTextDecorator::CharactersHaveSameStrongDirection(TChar aCh1, TChar aCh2)
+	{
+	return ((CharacterIsStrongLeftToRight(aCh1) && CharacterIsStrongLeftToRight(aCh2)) ||
+				(CharacterIsStrongRightToLeft(aCh1) && CharacterIsStrongRightToLeft(aCh2)));
+	}
+
+TBool CAknFepInlineTextDecorator::CharacterIsWeaklyDirectional(TChar aChar)
+	{
+	return ((aChar.GetBdCategory() == TChar::EEuropeanNumber) ||
+			(aChar.GetBdCategory() == TChar::EEuropeanNumberSeparator) ||
+			(aChar.GetBdCategory() == TChar::EEuropeanNumberTerminator) ||
+			(aChar.GetBdCategory() == TChar::EArabicNumber) ||
+			(aChar.GetBdCategory() == TChar::ECommonNumberSeparator));
+	}
+
+TBool CAknFepInlineTextDecorator::CharacterIsSeparator(TChar aChar)
+	{
+	return ((aChar.GetBdCategory() == TChar::EParagraphSeparator) || 
+			(aChar.GetBdCategory() == TChar::ESegmentSeparator));
+	}
+
+TBool CAknFepInlineTextDecorator::CharacterIsNeutral(TChar aChar)
+	{
+	return ((aChar.GetBdCategory() == TChar::EWhitespace) || 
+			(aChar.GetBdCategory() == TChar::EOtherNeutral));
+	}
+
+void CAknFepInlineTextDecorator::DecorateNeutralCharacters(
+	const TDesC& aInlineText,
+	TDes& aDecoratedText,
+	TInt& aPositionOfInsertionPointInInlineText,
+	TChar aPreviousCharacter,
+	TBool aRTLParagraph,
+    TBool aInputDirectionIsRTL)
+	{
+
+	TChar curCh;
+	TChar prevCh = aPreviousCharacter;
+	TBuf<ESingleCharacter> insertBuf(ESingleCharacter);
+
+	for (TInt ii = 0; ii < aInlineText.Length(); ii++)
+		{
+		curCh = aInlineText[ii];
+		aDecoratedText.Append(curCh);
+
+		if (CharacterIsNeutral(curCh))
+			{
+			// mark the neutral character with appropriate direction markers if :
+			//
+			// 1. the input mode (lang) is opposed to the paragraph direction and 
+			//     previous character is not neutral
+			// 2. the input mode (lang) is opposed to the previous char direction
+			//     (=> charcater is entered inside existing block)
+			//
+			// Note that we need to increment the insertion point by 2 if the
+			// markers are inserted before it
+			//
+			if ((aInputDirectionIsRTL && !aRTLParagraph && !CharacterIsNeutral(prevCh)) ||
+				(aInputDirectionIsRTL &&  CharacterIsStrongLeftToRight(prevCh)))
+				{ // mark neutral with RLM
+				insertBuf[0]=ERightToLeftMark;
+				aDecoratedText.Insert(aDecoratedText.Length() -1, insertBuf);
+				aDecoratedText.Append(insertBuf);
+				
+				if (aPositionOfInsertionPointInInlineText > ii)
+					aPositionOfInsertionPointInInlineText+=ETwoCharacters;
+				}
+
+			else if ((!aInputDirectionIsRTL && aRTLParagraph && !CharacterIsNeutral(prevCh)) ||
+					 (!aInputDirectionIsRTL && CharacterIsStrongRightToLeft(prevCh)))
+				{ // mark neutral with LRM
+				insertBuf[0]=ELeftToRightMark;
+				aDecoratedText.Insert(aDecoratedText.Length() -1, insertBuf);
+				aDecoratedText.Append(insertBuf);
+				
+				if (aPositionOfInsertionPointInInlineText > ii)
+					aPositionOfInsertionPointInInlineText+=ETwoCharacters;
+				}
+			}
+		prevCh = curCh;
+		}
+	}
+