/// <summary> /// Joining groups text, uses first group type as result group type /// </summary> private static TextGroup JoinGroups(IList <TextGroup> groups) { if (groups.Count == 0) { return(null); } // the new group type TextGroupType type = groups[0].Type; var sb = new StringBuilder(); foreach (TextGroup g in groups) { sb.Append(g.Text); } return(new TextGroup(type, sb)); }
public TextGroup(TextGroupType type, StringBuilder text) { Type = type; Text = text; }
public TextGroup(TextGroupType type) { Type = type; Text = new StringBuilder(); }
/// <summary> /// Reordering RTL groups to display corrently in LTR context /// </summary> private static List <TextGroup> ReorderRtlGroupsForLtr(List <TextGroup> strGroups) { var lstFinal = new List <TextGroup>(); TextGroupType lastGroupType = TextGroupType.Start; var lstTemp = new List <TextGroup>(); // previous command required to skip the upcoming group bool skipTheNextGroup = false; Func <TextGroupAction?> commandToDo = null; for (int i = 0; i < strGroups.Count; i++) { TextGroupAction textGroupAction = TextGroupAction.FlushLastAndJustAdd; TextGroup group = strGroups[i]; TextGroupType thisGroupType = group.Type; TextGroupType?changeLastGroupType = null; // ----------------------------- // Initializations int nextItemIndex = i + 1; int futureItemIndex = i + 2; int previousItemIndex = i - 1; TextGroup nextItem = null, futureItem = null; TextGroup previousItem = null; if (nextItemIndex < strGroups.Count) { nextItem = strGroups[nextItemIndex]; } if (futureItemIndex < strGroups.Count) { futureItem = strGroups[futureItemIndex]; } if (previousItemIndex >= 0 && previousItemIndex < strGroups.Count) { previousItem = strGroups[previousItemIndex]; } // ------------------------- // conditions // ------------------------- // the previous action requires this group to be skipped if (skipTheNextGroup) { textGroupAction = TextGroupAction.SkipThis; skipTheNextGroup = false; } else if (thisGroupType == TextGroupType.Space) { // Status = 1 if (lastGroupType == TextGroupType.Start) { textGroupAction = TextGroupAction.FlushLastAndJustAdd; } else { textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } else if (thisGroupType == TextGroupType.English) { if (nextItem != null) { if (nextItem.Type == TextGroupType.Persian) { // status 5 textGroupAction = TextGroupAction.JoinCheckedThenFlush; } else if (nextItem.Type == TextGroupType.English) { // impossoble textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (nextItem.Type == TextGroupType.Number) { // staus = 16 textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (nextItem.Type == TextGroupType.Symbol) { // status 15 textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (nextItem.Type == TextGroupType.Space) { if (futureItem == null) { // status 8 textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (futureItem.Type == TextGroupType.Persian) { // status = ?? textGroupAction = TextGroupAction.JoinCheckedThenFlush; } else if (futureItem.Type == TextGroupType.Symbol) { TextGroupType?foundType; int foundIndex; bool has = HasInFuture(strGroups, i, new[] { TextGroupType.English, }, new[] { TextGroupType.Symbol, TextGroupType.Number, TextGroupType.Space, }, out foundType, out foundIndex); if (has) { // status ?? textGroupAction = TextGroupAction.JoinThisAndNextCheckLast; skipTheNextGroup = true; } else { // status = ?? textGroupAction = TextGroupAction.JoinThisCheckLast; } } else { // status 14 textGroupAction = TextGroupAction.JoinThisAndNextCheckLast; skipTheNextGroup = true; } } else { throw new Exception("Unknown condition!"); textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } else { // statsu =?? textGroupAction = TextGroupAction.JoinCheckedThenFlush; } } else if (thisGroupType == TextGroupType.Persian) { if (nextItem != null) { if (nextItem.Type == TextGroupType.Persian) { // statusu =self textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (nextItem.Type == TextGroupType.English) { // staus 4 textGroupAction = TextGroupAction.JoinCheckedThenFlush; } else if (nextItem.Type == TextGroupType.Number) { // staus = 7 textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (nextItem.Type == TextGroupType.Symbol) { // status 9 textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (nextItem.Type == TextGroupType.Space) { if (futureItem == null) { // status 8 textGroupAction = TextGroupAction.JoinThisCheckLast; } else if (futureItem.Type == TextGroupType.English) { // status = ?? textGroupAction = TextGroupAction.JoinCheckedThenFlush; } else if (futureItem.Type == TextGroupType.Symbol) { TextGroupType?foundType; int foundIndex; bool has = HasInFuture(strGroups, i, new[] { TextGroupType.Persian, }, new[] { TextGroupType.Symbol, TextGroupType.Number, TextGroupType.Space, }, out foundType, out foundIndex); if (has) { // status ?? textGroupAction = TextGroupAction.JoinThisAndNextCheckLast; skipTheNextGroup = true; } else { // status = ?? textGroupAction = TextGroupAction.JoinThisCheckLast; } } else { // status 10 textGroupAction = TextGroupAction.JoinThisAndNextCheckLast; skipTheNextGroup = true; } } else { throw new Exception("Unknown condition!"); textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } else { // statsu =?? textGroupAction = TextGroupAction.JoinCheckedThenFlush; } } else if (thisGroupType == TextGroupType.Symbol) { int foundIndex; TextGroupType?prevAlphabet; // is there any alphabet in previous secions? bool hasAlphabetInPrevious = HasInPrevious(strGroups, i, new[] { TextGroupType.Persian, TextGroupType.English, }, new[] { TextGroupType.Symbol, TextGroupType.Space, TextGroupType.Number, }, out prevAlphabet, out foundIndex); if (hasAlphabetInPrevious) { TextGroupType?nextAlphabet; // is there any same alphabet in coming groups? bool hasAlphabetInNext = HasInFuture(strGroups, i, new[] { prevAlphabet.Value, }, new[] { TextGroupType.Symbol, TextGroupType.Space, TextGroupType.Number, }, out nextAlphabet, out foundIndex); if (hasAlphabetInNext) { // status=?? textGroupAction = TextGroupAction.DoCommand; commandToDo = () => // do TextGroupAction { // let the loop continute on the alphabet, intead of anything else foundIndex--; for (int index = i; index <= foundIndex; index++) { // adding all the groups in the range/ they behave same lstTemp.Add(strGroups[index]); } TextGroup combined = JoinGroups(lstTemp); lstTemp.Clear(); lstTemp.Add(combined); // changing index of current group/ skiping added groups i = foundIndex; // changing the last group type group = combined; // don't do anything return(TextGroupAction.SkipThis); }; } else { // no alphabet in upcoming group so ,bracket kind characters should be switched group.Text = ReverseBrackedKindChar(group.Text); if (prevAlphabet != null && prevAlphabet.Value == TextGroupType.English) { // in english, if there is number after symbol, orders changes TextGroupType?hasNumber; // is there any same alphabet in coming groups? bool hasNumberInNext = HasInFuture(strGroups, i, new[] { TextGroupType.Number, }, new[] { TextGroupType.Symbol, TextGroupType.Space, TextGroupType.Number, }, out nextAlphabet, out foundIndex); if (hasNumberInNext) { textGroupAction = TextGroupAction.JoinThisDontCheck; changeLastGroupType = prevAlphabet.Value; //// next group checks the type, needed group.Type = prevAlphabet.Value; } else { // status = 17, 18, 19, 20, 2 textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } else { // status = 17, 18, 19, 20, 2 textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } } else { // status = 17, 18, 19, 20, 2 textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } else if (thisGroupType == TextGroupType.Number) { int foundIndex; TextGroupType?prevAlphabet; // is there any alphabet in previous secions? bool hasAlphabetInPrevious = HasInPrevious(strGroups, i, new[] { TextGroupType.Persian, TextGroupType.English, }, new[] { TextGroupType.Symbol, TextGroupType.Space, TextGroupType.Number, }, out prevAlphabet, out foundIndex); if (hasAlphabetInPrevious) { TextGroupType?nextAlphabet; // is there any same alphabet in coming groups? bool hasAlphabetInNext = HasInFuture(strGroups, i, new[] { prevAlphabet.Value, }, new[] { TextGroupType.Symbol, TextGroupType.Space, TextGroupType.Number, }, out nextAlphabet, out foundIndex); if (hasAlphabetInNext) { textGroupAction = TextGroupAction.DoCommand; commandToDo = () => // do TextGroupAction { // let the loop continute on the alphabet, intead of anything else foundIndex--; for (int index = i; index <= foundIndex; index++) { // adding all the groups in the range/ they behave same lstTemp.Add(strGroups[index]); } TextGroup combined = JoinGroups(lstTemp); lstTemp.Clear(); lstTemp.Add(combined); // changing index of current group/ skiping added groups i = foundIndex; // chaning the last group type group = combined; // don't do anything return(TextGroupAction.SkipThis); }; } else { // is previous item alphabet? if (previousItem != null && (previousItem.Type == TextGroupType.Persian || previousItem.Type == TextGroupType.English)) { // status =?? textGroupAction = TextGroupAction.JoinThisDontCheck; changeLastGroupType = previousItem.Type; // next group checks the type, needed group.Type = previousItem.Type; } else { // is next item alphabet? if (nextItem != null && (nextItem.Type == TextGroupType.Persian || nextItem.Type == TextGroupType.English)) { // status =?? textGroupAction = TextGroupAction.JoinThisDontCheck; changeLastGroupType = nextItem.Type; // next group checks the type, needed group.Type = nextItem.Type; } else { // status = ?? textGroupAction = TextGroupAction.JoinThisDontCheck; } } } } else { if (nextItem != null && (nextItem.Type == TextGroupType.Persian || nextItem.Type == TextGroupType.English)) { // status =?? textGroupAction = TextGroupAction.JoinThisDontCheck; changeLastGroupType = nextItem.Type; // next group checks the type, needed group.Type = nextItem.Type; } else { // status = ?? textGroupAction = TextGroupAction.FlushLastAndJustAdd; } } } else { // status = ?? textGroupAction = TextGroupAction.FlushLastAndJustAdd; } // ------------------------- // performing the specified actions // ------------------------- // if any specific command requred! if (textGroupAction == TextGroupAction.DoCommand) { if (commandToDo != null) { // setting the result textGroupAction = commandToDo() ?? TextGroupAction.SkipThis; } } // the actions switch (textGroupAction) { // ------------------------ case TextGroupAction.FlushLastAndJustAdd: TextGroup combinedFlush = JoinGroups(lstTemp); if (combinedFlush != null) { lstFinal.Add(combinedFlush); } lstTemp.Clear(); // just add lstFinal.Add(group); break; // ------------------------ case TextGroupAction.JoinCheckedThenFlush: if (lstTemp.Count > 0 && lstTemp[0].Type != thisGroupType) { TextGroup combine1 = JoinGroups(lstTemp); if (combine1 != null) { lstFinal.Add(combine1); } lstTemp.Clear(); } // add to grouop first lstTemp.Add(group); TextGroup combine2 = JoinGroups(lstTemp); if (combine2 != null) { lstFinal.Add(combine2); } lstTemp.Clear(); break; // ------------------------ case TextGroupAction.JoinThisCheckLast: // check the previous type, if it differs then flush it! if (lstTemp.Count > 0 && lstTemp[0].Type != thisGroupType) { TextGroup combine = JoinGroups(lstTemp); if (combine != null) { lstFinal.Add(combine); } lstTemp.Clear(); } lstTemp.Add(group); break; // ------------------------ case TextGroupAction.JoinThisAndNextCheckLast: // check the previous type, if it differs then flush it! if (lstTemp.Count > 0 && lstTemp[0].Type != thisGroupType) { TextGroup combine = JoinGroups(lstTemp); if (combine != null) { lstFinal.Add(combine); } lstTemp.Clear(); } lstTemp.Add(group); if (nextItem != null) { lstTemp.Add(nextItem); } break; // ------------------------ case TextGroupAction.JoinThisDontCheck: lstTemp.Add(group); break; // ------------------------ case TextGroupAction.DoCommand: // already done! break; // ------------------------ case TextGroupAction.SkipThis: // do nothing! break; } // saving last group type // check if custom type is requested if (changeLastGroupType != null) { lastGroupType = changeLastGroupType.Value; } else { lastGroupType = group.Type; } } TextGroup combineFinal = JoinGroups(lstTemp); if (combineFinal != null) { lstFinal.Add(combineFinal); } lstFinal.Reverse(); return(lstFinal); }