Click here to Skip to main content
15,881,709 members
Articles / Desktop Programming / XAML

Silverlight 1.1 Hebrew and Arabic Language Support

Rate me:
Please Sign up or sign in to vote.
4.05/5 (8 votes)
31 Jan 2008Ms-PL7 min read 44K   290   10  
An article presenting Silverlight 1.1 Hebrew and Arabic language support
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using JustinAngelNet.Silverlight.Framework;
using NBiDi.Extensions;

namespace JustinAngelNet.SilverlightRTL.RTL
{
    public static class SilverlightAlignmenetParagraphsToRowsAlgorithem
    {
        public static List<TextBlock> RtlTextBlockToWrappingScenarios(TextBlock textBlockToRTL, bool ForceAllParagraphsAsRTL)
        {
            List<TextBlock> TextBlocksAttachedToCanvas = new List<TextBlock>();
            Canvas ParentOfTextBlockToRTL = (Canvas)textBlockToRTL.Parent;
            double curHeightOffsetForBreakLines = 0;
            string lastLineText = string.Empty;
            foreach (string curParagraph in NBiDiExtensions.SplitToParagraphs(textBlockToRTL.Text))
            {
                if (!string.IsNullOrEmpty(curParagraph))
                {
                    curHeightOffsetForBreakLines = SplitParagraphIntoLinesWithNoBrokenWordsNoBrokwnNumbersCorrectWrappingAndCorrectPlacemenetOnScreen(textBlockToRTL, ParentOfTextBlockToRTL, curHeightOffsetForBreakLines, curParagraph, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, lastLineText);
                }
                else
                {
                    curHeightOffsetForBreakLines = AddEmptyLine(textBlockToRTL, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, curHeightOffsetForBreakLines, curParagraph, lastLineText);
                }
            }
            ParentOfTextBlockToRTL.Children.Remove(textBlockToRTL);

            return TextBlocksAttachedToCanvas;
        }

        private static double AddEmptyLine(TextBlock textBlockToRTL, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, double curHeightOffsetForBreakLines, string curParagraph, string lastLineText)
        {
            double textBlockToRTLCanvasTop = (double)textBlockToRTL.GetValue(Canvas.TopProperty);
            double textBlockToRTLCanvasLeft = (double)textBlockToRTL.GetValue(Canvas.LeftProperty);
            TextBlock newTextBlockForEmptyLine = InitlizeNewTextBlock(textBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, new List<char>(new char[] { ' ', ' ' }), ForceAllParagraphsAsRTL, lastLineText);
            curHeightOffsetForBreakLines += newTextBlockForEmptyLine.ActualHeight;
            TextBlocksAttachedToCanvas.Add(newTextBlockForEmptyLine);
            return curHeightOffsetForBreakLines;
        }

        private static double SplitParagraphIntoLinesWithNoBrokenWordsNoBrokwnNumbersCorrectWrappingAndCorrectPlacemenetOnScreen(TextBlock textBlockToRTL, Canvas ParentOfTextBlockToRTL, double curHeightOffsetForBreakLines, string curParagraph, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, string lastLineText)
        {
            double textBlockToRTLCanvasTop = (double)textBlockToRTL.GetValue(Canvas.TopProperty);
            double textBlockToRTLCanvasLeft = (double)textBlockToRTL.GetValue(Canvas.LeftProperty);

            List<char> queueOfCharsInStringToBeAdded = new List<char>(curParagraph.ToCharArray());

            TextBlock newTextBlockForOneLineOnly = InitlizeNewTextBlock(textBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, queueOfCharsInStringToBeAdded, ForceAllParagraphsAsRTL, lastLineText);

            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded))
            {
                IterateOverAllRemainingLettersNotOnScreenPutThemInLinesWithCorrectSyntax(textBlockToRTL, ParentOfTextBlockToRTL, ref curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, textBlockToRTLCanvasLeft, queueOfCharsInStringToBeAdded, ref newTextBlockForOneLineOnly, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, ref lastLineText);
            }

            curHeightOffsetForBreakLines = AttachNewTextBlockAfterFinishedDeterminingItsText(textBlockToRTL, ParentOfTextBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasLeft, newTextBlockForOneLineOnly, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, lastLineText);
            return curHeightOffsetForBreakLines;
        }

        private static void IterateOverAllRemainingLettersNotOnScreenPutThemInLinesWithCorrectSyntax(TextBlock textBlockToRTL, Canvas ParentOfTextBlockToRTL, ref double curHeightOffsetForBreakLines, string curParagraph, double textBlockToRTLCanvasTop, double textBlockToRTLCanvasLeft, List<char> queueOfCharsInStringToBeAdded, ref TextBlock newTextBlockForOneLineOnly, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, ref string lastLineText)
        {
            double actualHeightOfNewTextBlockBegingingIteration = newTextBlockForOneLineOnly.ActualHeight;

            newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);

            if ((IsNotQueueEmpty(queueOfCharsInStringToBeAdded)) &&
                actualHeightOfNewTextBlockBegingingIteration != newTextBlockForOneLineOnly.ActualHeight)
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                string textBeforeWholeHandle = newTextBlockForOneLineOnly.Text;


                HandleAllByMovingUntilWhitespace(textBlockToRTL, queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                ShrinkDownWrapWithOverflowToOneLine(actualHeightOfNewTextBlockBegingingIteration,
                                                    queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                //HandleWithBrokwnWords(textBlockToRTL, queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                //HandleWithBrokenNumbersAndMoveSpacersToTextBlock(textBlockToRTL, queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);

                CheckIfWrapLeftEmptyTextBlock_BecauseOfLongWord_AndIfSoRestoreOriginalValue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, textBeforeWholeHandle);

                if (IsNotQueueEmpty(queueOfCharsInStringToBeAdded))
                {
                    string valueBeforeBiDi = newTextBlockForOneLineOnly.Text;

                    curHeightOffsetForBreakLines = AttachNewTextBlockAfterFinishedDeterminingItsText(textBlockToRTL, ParentOfTextBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasLeft, newTextBlockForOneLineOnly, ForceAllParagraphsAsRTL, TextBlocksAttachedToCanvas, lastLineText);
                    lastLineText = valueBeforeBiDi;

                    newTextBlockForOneLineOnly = InitlizeNewTextBlock(textBlockToRTL, curHeightOffsetForBreakLines, curParagraph, textBlockToRTLCanvasTop, queueOfCharsInStringToBeAdded, ForceAllParagraphsAsRTL, lastLineText);
                }
            }
        }

        private static void ShrinkDownWrapWithOverflowToOneLine(double actualHeightOfNewTextBlockBegingingIteration, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            while (newTextBlockForOneLineOnly.ActualHeight != actualHeightOfNewTextBlockBegingingIteration)
            {
                newTextBlockForOneLineOnly.Width++;
                newTextBlockForOneLineOnly.TextWrapping = newTextBlockForOneLineOnly.TextWrapping;
            }
        }

        private static void HandleAllByMovingUntilWhitespace(TextBlock textBlockToRTL, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            if (textBlockToRTL.TextWrapping == TextWrapping.WrapWithOverflow)
            {
                if (!NBiDiExtensions.IsWhitespace(GetLastCharInTextBlock(newTextBlockForOneLineOnly)))
                    while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                           && !NBiDiExtensions.IsWhitespace(Peek(queueOfCharsInStringToBeAdded)))
                    {
                        newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                    }

                while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                       && NBiDiExtensions.IsWhitespace(Peek(queueOfCharsInStringToBeAdded)))
                    newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
            }
            else if (textBlockToRTL.TextWrapping == TextWrapping.Wrap)
            {
                while (newTextBlockForOneLineOnly.Text.Length != 0
                       && !NBiDiExtensions.IsWhitespace(GetLastCharInTextBlock(newTextBlockForOneLineOnly)))
                {
                    RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                }
            }
        }

        private static string RemoveFirstCharcter(string text)
        {
            return text.Remove(0, 1);
        }

        private static string RemoveFirstCharcterIfRLOorLRO(string text, ref char? firstCharRemoved)
        {
            if (NBiDiExtensions.LTRFirstCharMark == text[0]
                || NBiDiExtensions.RTLFirstCharMark == text[0])
            {
                firstCharRemoved = text[0];
                return text.Remove(0, 1);
            }
            else
                return text;
        }

        private static bool IsNotQueueEmpty(List<char> queueOfCharsInStringToBeAdded)
        {
            return queueOfCharsInStringToBeAdded.Count != 0;
        }

        private static void CheckIfWrapLeftEmptyTextBlock_BecauseOfLongWord_AndIfSoRestoreOriginalValue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, string textBeforeWholeHandle)
        {
            if (IsTextBlockEmpty(newTextBlockForOneLineOnly))
            {
                while (newTextBlockForOneLineOnly.Text != textBeforeWholeHandle)
                {
                    newTextBlockForOneLineOnly.Text +=
                        GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                }
            }
        }

        private static bool IsTextBlockEmpty(TextBlock newTextBlockForOneLineOnly)
        {
            return !IsNotTextBlockEmpty(newTextBlockForOneLineOnly);
        }

        private static bool IsNotTextBlockEmpty(TextBlock newTextBlockForOneLineOnly)
        {
            return newTextBlockForOneLineOnly.Text.Length != 0;
        }

        private static void HandleWithBrokenNumbersAndMoveSpacersToTextBlock(TextBlock textBlockToRTL, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            if (textBlockToRTL.TextWrapping == TextWrapping.WrapWithOverflow)
                while (true && IsNotQueueEmpty(queueOfCharsInStringToBeAdded))
                {
                    bool AdjustmentsMade = false;

                    //AdjustmentsMade = GetlAllSpacerFromQueueToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);
                    //AdjustmentsMade = GetNumbersAfterPunctioationOrNumbersFromQueueToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);
                    //AdjustmentsMade = GetrPunctioationAfterNumbersFromQueueToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);

                    if (!AdjustmentsMade)
                        break;
                }
            else if (textBlockToRTL.TextWrapping == TextWrapping.Wrap)
                while (true && newTextBlockForOneLineOnly.Text.Length != 0)
                {
                    bool AdjustmentsMade = false;

                    //AdjustmentsMade = ReturnNumbersAfterPunctioationOrNumbersFromTextBlockToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);
                    //AdjustmentsMade = ReturnPunctioationAfterNumbersFromTextBlockToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly, AdjustmentsMade);

                    if (!AdjustmentsMade)
                        break;
                }
        }

        private static bool ReturnPunctioationAfterNumbersFromTextBlockToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (newTextBlockForOneLineOnly.Text.Length != 0
                   && NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                   && NBiDiExtensions.IsPunctionChar(Peek(queueOfCharsInStringToBeAdded)))
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static bool ReturnNumbersAfterPunctioationOrNumbersFromTextBlockToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (newTextBlockForOneLineOnly.Text.Length != 0
                   && ((NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                        || NBiDiExtensions.IsPunctionChar(GetLastCharInTextBlock(newTextBlockForOneLineOnly))))
                   && NBiDiExtensions.IsNumberCharcter(Peek(queueOfCharsInStringToBeAdded)))
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static char GetLastCharInTextBlock(TextBlock newTextBlockForOneLineOnly)
        {
            return newTextBlockForOneLineOnly.Text[newTextBlockForOneLineOnly.Text.Length - 1];
        }

        private static void HandleWithBrokwnWords(TextBlock textBlockToRTL, List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            if (textBlockToRTL.TextWrapping == TextWrapping.WrapWithOverflow)
            {
                GetAllBrokenWordToTextBlock(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
            }
            else if (textBlockToRTL.TextWrapping == TextWrapping.Wrap)
            {
                ReturnAllBrokenWordsToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
            }
        }

        private static bool GetrPunctioationAfterNumbersFromQueueToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                   && NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                   && NBiDiExtensions.IsPunctionChar(Peek(queueOfCharsInStringToBeAdded)))
            {
                newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static bool GetNumbersAfterPunctioationOrNumbersFromQueueToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                   && (NBiDiExtensions.IsNumberCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))
                       || NBiDiExtensions.IsPunctionChar(GetLastCharInTextBlock(newTextBlockForOneLineOnly)))
                   && NBiDiExtensions.IsNumberCharcter(Peek(queueOfCharsInStringToBeAdded)))
            {
                newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static bool GetlAllSpacerFromQueueToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly, bool AdjustmentsMade)
        {
            while (IsNotQueueEmpty(queueOfCharsInStringToBeAdded)
                   && NBiDiExtensions.IsSpacerCharcter(Peek(queueOfCharsInStringToBeAdded)))
            {
                newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
                AdjustmentsMade = true;
            }
            return AdjustmentsMade;
        }

        private static void GetAllBrokenWordToTextBlock(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            while ((IsNotQueueEmpty(queueOfCharsInStringToBeAdded)) &&
                   (!NBiDiExtensions.IsSpacerCharcter(Peek(queueOfCharsInStringToBeAdded))))
            {
                newTextBlockForOneLineOnly.Text +=
                    GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
            }
        }

        private static void ReturnAllBrokenWordsToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            while ((newTextBlockForOneLineOnly.Text.Length != 0) &&
                   (!NBiDiExtensions.IsSpacerCharcter(GetLastCharInTextBlock(newTextBlockForOneLineOnly))))
            {
                RemoveLastCharFromTextBlockAndReturnToQueue(queueOfCharsInStringToBeAdded, newTextBlockForOneLineOnly);
            }
        }

        private static void RemoveLastCharFromTextBlockAndReturnToQueue(List<char> queueOfCharsInStringToBeAdded, TextBlock newTextBlockForOneLineOnly)
        {
            InsertAsFirst(queueOfCharsInStringToBeAdded, GetLastCharInTextBlock(newTextBlockForOneLineOnly));
            newTextBlockForOneLineOnly.Text = newTextBlockForOneLineOnly.Text.Remove(newTextBlockForOneLineOnly.Text.Length - 1, 1);
        }

        private static double AttachNewTextBlockAfterFinishedDeterminingItsText(TextBlock textBlockToRTL, Canvas ParentOfTextBlockToRTL, double curHeightOffsetForBreakLines, string curParagraph, double textBlockToRTLCanvasLeft, TextBlock newTextBlockForOneLineOnly, bool ForceAllParagraphsAsRTL, List<TextBlock> TextBlocksAttachedToCanvas, string lastLineText)
        {
            SetTextForTextBlockBasedOnIfNeedsRTLAndHasNonRTLLTRBegining(curParagraph, newTextBlockForOneLineOnly, lastLineText);
            newTextBlockForOneLineOnly.TextWrapping = TextWrapping.NoWrap;
            newTextBlockForOneLineOnly.Height = newTextBlockForOneLineOnly.ActualHeight;
            SetCanvasLeftForNewTextBlock(curParagraph, ForceAllParagraphsAsRTL, textBlockToRTL, textBlockToRTLCanvasLeft, newTextBlockForOneLineOnly);
            curHeightOffsetForBreakLines += newTextBlockForOneLineOnly.ActualHeight;
            ParentOfTextBlockToRTL.Children.Add(newTextBlockForOneLineOnly);
            TextBlocksAttachedToCanvas.Add(newTextBlockForOneLineOnly);
            return curHeightOffsetForBreakLines;
        }

        private static void SetTextForTextBlockBasedOnIfNeedsRTLAndHasNonRTLLTRBegining(string curParagraph, TextBlock newTextBlockForOneLineOnly, string lastLineText)
        {
            if (!NBiDiExtensions.IsTextNeedAlignToRight(curParagraph))
                newTextBlockForOneLineOnly.Text = NBidi.NBidi.LogicalToVisual(newTextBlockForOneLineOnly.Text);
            else
            {
                string TextNotToAlign;
                string textToBidi;
                CutTextNotToAlignBecauseOfStartAndCutTextToBiDi(newTextBlockForOneLineOnly, out TextNotToAlign, out textToBidi, lastLineText);

                newTextBlockForOneLineOnly.Text = NBidi.NBidi.LogicalToVisual(textToBidi) + TextNotToAlign;
            }
        }

        private static void CutTextNotToAlignBecauseOfStartAndCutTextToBiDi(TextBlock newTextBlockForOneLineOnly, out string TextNotToAlign, out string textToBidi, string lastLineText)
        {
            string textWithBadStart = RemoveFirstCharcter(newTextBlockForOneLineOnly.Text);
            int i;
            int j = -1;
            for (i = 0; i < textWithBadStart.Length; i++)
            {
                if (NBiDiExtensions.IsRTLChar(textWithBadStart[i])
                    || NBiDiExtensions.IsLTRChar(textWithBadStart[i]))
                {

                    break;
                }
            }
            if (i > 0)
                i--;

            //if (i != 0)
            for (j = i; j != -1; j--)
            {
                if (NBiDiExtensions.IsNumberCharcter(textWithBadStart[j]))
                {
                    break;
                }
            }
            if (j != -1)
                j++;

            // no need for pre-NBiDi cutting
            if (j == -1)
            {
                TextNotToAlign = string.Empty;
                textToBidi = newTextBlockForOneLineOnly.Text;
            }
            else
            {


                char firstChar = newTextBlockForOneLineOnly.Text[0];
                    
                if (/*NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText).HasValue
                        && NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText).GetValueOrDefault()
                        && firstCharRemoved.HasValue
                        && firstCharRemoved.GetValueOrDefault() == NBiDiExtensions.RTLFirstCharMark*/
                    GetIndectionFromPreviousLine(lastLineText, firstChar) == NBiDiExtensions.RTLFirstCharMark)
                    TextNotToAlign = NBiDiExtensions.ReverseStringByWhiteSpaceForNumbersOnly(textWithBadStart.Substring(0, j));
                else
                    TextNotToAlign = textWithBadStart.Substring(0, j);
                    
                textToBidi = firstChar + textWithBadStart.Substring(j, textWithBadStart.Length - j);

            }
        }

        //private static void CutTextNotToAlignBecauseOfStartAndCutTextToBiDi(TextBlock newTextBlockForOneLineOnly, out string TextNotToAlign, out string rest, string lastLineText)
        //{
        //    string textWithBadStart = RemoveFirstCharcter(newTextBlockForOneLineOnly.Text);
        //    int i;
        //    int j = -1;
        //    for (i = 0; i < textWithBadStart.Length; i++)
        //    {
        //        if (NBiDiExtensions.IsRTLChar(textWithBadStart[i])
        //            || NBiDiExtensions.IsLTRChar(textWithBadStart[i]))
        //        {

        //            break;
        //        }
        //    }
        //    if (i > 0)
        //        i--;

        //    //if (i != 0)
        //    for (j = i; j != -1; j--)
        //    {
        //        if (NBiDiExtensions.IsNumberCharcter(textWithBadStart[j]))
        //        {
        //            break;
        //        }
        //    }
        //    if (j != -1)
        //        j++;

        //    // no need for pre-NBiDi cutting
        //    if (j == -1)
        //    {
        //        TextNotToAlign = string.Empty;
        //        rest = newTextBlockForOneLineOnly.Text;
        //    }
        //    else
        //    {
        //        char firstChar = newTextBlockForOneLineOnly.Text[0];

        //        char indectionFromPreviousLine = GetIndectionFromPreviousLine(lastLineText, firstChar);
        //        TextNotToAlign = NBidi.NBidi.LogicalToVisual(indectionFromPreviousLine + textWithBadStart.Substring(0, j));
        //        rest = firstChar + textWithBadStart.Substring(j, textWithBadStart.Length - j);
        //    }
        //}

        private static char GetIndectionFromPreviousLine(string lastLineText, char firstChar)
        {
            bool? isLastLineRTL = NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText);

            char indectionFromPreviousLine;
            if (isLastLineRTL.HasValue)
                indectionFromPreviousLine = NBiDiExtensions.GetLTRorRTLStarterCharcterForLine(isLastLineRTL.GetValueOrDefault());
            else
                indectionFromPreviousLine = firstChar;
            return indectionFromPreviousLine;
        }

        private static char? GetIndectionFromPreviousLine(string lastLineText)
        {
            bool? isLastLineRTL = NBiDiExtensions.GetLTRorRTLStarterCharcterForLineFromLastCharToFirst(lastLineText);

            char? indectionFromPreviousLine = null;
            if (isLastLineRTL.HasValue)
            {
                if (isLastLineRTL.GetValueOrDefault())
                    indectionFromPreviousLine = NBidi.BidiChars.RLE;
                else
                    indectionFromPreviousLine = NBidi.BidiChars.LRE;
            }
            
            //   indectionFromPreviousLine = NBiDiExtensions.GetLTRorRTLStarterCharcterForLine(isLastLineRTL.GetValueOrDefault());
            
           

            return indectionFromPreviousLine;
        }


        private static TextBlock InitlizeNewTextBlock(TextBlock textBlockToRTL, double curHeightOffsetForBreakLines, string curParagraph, double textBlockToRTLCanvasTop, List<char> queueOfCharsInStringToBeAdded, bool ForceAllParagraphsAsRTL, string lastLineText)
        {
            TextBlock newTextBlockForOneLineOnly = SilverlightExtensions.Clone(textBlockToRTL);
            newTextBlockForOneLineOnly.Text = GetFirstUnicodeRTLorLTRcharcter(textBlockToRTL, curParagraph, ForceAllParagraphsAsRTL, lastLineText).ToString();
            newTextBlockForOneLineOnly.SetValue(Canvas.TopProperty,
                                                textBlockToRTLCanvasTop +
                                                curHeightOffsetForBreakLines);
            newTextBlockForOneLineOnly.Text += GetFirstAndRemoveIt(queueOfCharsInStringToBeAdded);
            return newTextBlockForOneLineOnly;
        }

        private static void SetCanvasLeftForNewTextBlock(string curParagraph, bool ForceAllAsRTL, TextBlock textBlockToRTL, double textBlockToRTLCanvasLeft, TextBlock newTextBlockForOneLineOnly)
        {
            if (NBiDiExtensions.IsTextNeedAlignToRight(curParagraph) || ForceAllAsRTL)
            {
                double fixMove = textBlockToRTL.Width -
                                 newTextBlockForOneLineOnly.ActualWidth;
                double mirrorCanvasLeftForTextBlock = textBlockToRTLCanvasLeft + fixMove;
                newTextBlockForOneLineOnly.SetValue(Canvas.LeftProperty, mirrorCanvasLeftForTextBlock);

            }
            else
            {
                newTextBlockForOneLineOnly.SetValue(Canvas.LeftProperty, textBlockToRTLCanvasLeft);
            }
        }

        private static string GetFirstUnicodeRTLorLTRcharcter(TextBlock textBlockToRTL, string curParagraph, bool ForceALLAsRTL, string lastLineText)
        {
            char firstLTRorRTLCharForFirstLineInParagraph =
                NBiDiExtensions.GetLTRorRTLStarterCharcterForLine(
                    NBiDiExtensions.IsTextNeedAlignToRight(curParagraph) || ForceALLAsRTL);

            return firstLTRorRTLCharForFirstLineInParagraph.ToString();

            char? indectionFromPreviousSentence = GetIndectionFromPreviousLine(lastLineText);

            if (indectionFromPreviousSentence.HasValue
                && indectionFromPreviousSentence.GetValueOrDefault() != firstLTRorRTLCharForFirstLineInParagraph)
                return indectionFromPreviousSentence.GetValueOrDefault().ToString() + firstLTRorRTLCharForFirstLineInParagraph.ToString();
            else
                return firstLTRorRTLCharForFirstLineInParagraph.ToString();
        }

        private static char Peek(List<char> list)
        {
            return list[0];
        }

        private static void InsertAsFirst(List<char> list, char charToAdd)
        {
            list.Insert(0, charToAdd);
        }

        private static char GetFirstAndRemoveIt(List<char> list)
        {
            char ReturnValue = list[0];
            list.RemoveAt(0);
            return ReturnValue;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
JustinAngel.Net, Senior .Net consultant
Israel Israel
Justin-Josef Angel is a C# Microsoft Most Valuable professional, a Senior .Net consultant in Israel with 4 years of .Net experience and has 8 years of Web experience.

Justin's been working this past year on two Enterprise sized Silverlight projects with his customers. During that time he's gained a real-insight into Silverlight's inner workings and how to integrate Silverlight into the real world of software development. Additionally, During that time he's developed a few well-known projects like the "Silverlight 1.0 Javascript Intellisense", "Silverlight 1.1 Hebrew & Arabic Languages support" and a few others you might know.

Justin is also a seasoned presenter with an impressive track-record of talking in front of thousands of people in Israel.

Justin owns the first .Net blog written in Hebrew - http://www.JustinAngel.Net .
And he also owns an additional blog with mixed Hebrew & English content - http://blogs.Microsoft.co.il/blogs/JustinAngel.

A full list of his articles (all 100+ of them) can be found at: http://www.JustinAngel.Net/#index




Comments and Discussions