public void TestNormalWrap() { HTMLDualTagFormatting u = new HTMLDualTagFormatting("uu"); HTMLDualTagFormatting b = new HTMLDualTagFormatting("b"); string toTest = "<uu><b>aa</b></uu>"; WrappedFormat r = new WrappedFormat(u, new Position(4, 13)); r.AddRule(b, Position.OverlapType.Total); Position mod = r.ModifiedPosition; Assert.AreEqual(0, mod.Start); Assert.AreEqual(2, mod.End); }
private static void FixDict(Dictionary <TextFormattingRule, ICollection <Position> > dict, WrappedFormat item) { if (!item.wrappedRules().Any()) { return; } if (!dict[item.Rule].Remove(item.Position)) { throw new InvalidOperationException("wrapped value is not contained."); } dict[item.Rule].Add(item.ModifiedPosition); }
public static result ProcessString(string input, IEnumerable <TextFormattingRule> rules) { //TODO: This algortihm is terribly complicated due to it being single-pass. //Would make more sent to convert to multipass. var dict = new Dictionary <TextFormattingRule, ICollection <Position> >(); List <Tuple <TextFormattingRule, IEnumerator <Position> > > positionEnumerator = generateFirstPositions(rules, input); //Potentially, tags can be wrapped: //<b><u>...</u></b> //<b>aa<u>bb</u>cc</b>dd //as this goes through sequentially, in each instance it would be: //<b><u> //Once u is modifed, b will also need to be shifted as b wraps u. var possibleOverlaps = new List <WrappedFormat>(); string modifiedInput = input; int totalShift = 0; while (positionEnumerator.Count > 0) { //sort the items positionEnumerator.Sort((a, b) => a.Item2.Current.CompareTo(b.Item2.Current)); IEnumerator <Position> currentEnumerator = positionEnumerator[0].Item2; var rule = positionEnumerator[0].Item1; //The position in the original string. Position toProcess = currentEnumerator.Current; //remove any non overlaps from PossibleOverlaps totalShift = UpdatePossibleOverlaps(dict, possibleOverlaps, totalShift, rule, toProcess); var currentShift = getProcessPosition(possibleOverlaps, toProcess); var shiftToUse = new Tuple <int, int>(currentShift.Item1 + totalShift, currentShift.Item2 + totalShift); //The position in the current string. Position processPosition = toProcess.Shift(shiftToUse); //The position in the string after .Process() Position outputPosition = processPosition.Shift(rule.ShiftAmount); string newInput = rule.Process(modifiedInput, processPosition); Debug.Assert(modifiedInput.Length - newInput.Length == rule.TotalLength); //foreach (var overlap in possibleOverlaps) // HandleOverlap(dict, overlap, rule); if (!dict.ContainsKey(rule)) { dict.Add(rule, new List <Position>()); } //Note: This works on the position of the original string, hence using toProcess. var wf = new WrappedFormat(rule, outputPosition); wf.OriginalPosition = toProcess; possibleOverlaps.Add(wf); dict[rule].Add(outputPosition); if (!currentEnumerator.MoveNext()) { positionEnumerator.Remove(positionEnumerator[0]); } modifiedInput = newInput; } foreach (var item in possibleOverlaps) { FixDict(dict, item); } return(new result() { Value = modifiedInput, Positions = dict }); }