Пример #1
0
        public void OrcBoxRun()
        {
            // Run 0
            string part0 = "abc";
            string part1 = "\xfffc";
            string part2 = "defg";

            AssembledStyles styles     = new AssembledStyles().WithWs(wsEn);
            StringClientRun clientRun0 = new StringClientRun(part0 + part1 + part2, styles);
            var             clientRuns = new List <IClientRun>();

            clientRuns.Add(clientRun0);

            BlockBox box = new BlockBox(styles.WithWs(wsFrn), Color.Red, 72000, 36000);

            TextSource source = new TextSource(clientRuns, (run, offset) => box);

            MapRun[] runs = source.Runs;
            Assert.AreEqual(3, runs.Length);
            VerifyRun(0, clientRun0, 0, 0, part0, runs[0], "first run of complex source with box");
            int len = part0.Length;

            VerifyRun(len, box, len, part0.Length, part1, runs[1], "2nd run of complex source with box");
            len += 1;
            VerifyRun(len, clientRun0, len, part0.Length + 1, part2, runs[2], "3rd run of complex source with box");
            len += part2.Length;
            Assert.AreEqual(len, source.Length, "length of complex source with box");
            VerifyCharProps(source, part0.Length, wsFrn, part0.Length, part0.Length + 1, "props of box");
        }
Пример #2
0
        public void MlsRuns()
        {
            string           part1 = "abc def";
            IViewMultiString mls   = new MultiAccessor(wsEn, wsEn);

            mls.set_String(wsEn, tsf.MakeString(part1, wsEn));
            AssembledStyles styles    = new AssembledStyles();
            MlsClientRun    clientRun = new MlsClientRun(mls, styles.WithWs(wsEn));

            Assert.AreEqual(1, clientRun.UniformRunCount);
            Assert.AreEqual(part1, clientRun.UniformRunText(0));
            AssembledStyles style1 = clientRun.UniformRunStyles(0);

            Assert.AreEqual(wsEn, style1.Ws);
            Assert.AreEqual(0, clientRun.UniformRunStart(0));
            Assert.AreEqual(part1.Length, clientRun.UniformRunLength(0));

            string     part2 = " ghi";
            ITsStrBldr bldr  = mls.get_String(wsEn).GetBldr();

            bldr.Replace(part1.Length, part1.Length, part2, ttpFrn);
            IViewMultiString multibldr = new MultiAccessor(wsEn, wsEn);

            multibldr.set_String(wsFrn, bldr.GetString());
            MlsClientRun clientRun2 = new MlsClientRun(multibldr, styles.WithWs(wsFrn));

            Assert.AreEqual(2, clientRun2.UniformRunCount);
            Assert.AreEqual(part1, clientRun2.UniformRunText(0));
            Assert.AreEqual(part2, clientRun2.UniformRunText(1));
            style1 = clientRun2.UniformRunStyles(0);
            Assert.AreEqual(wsEn, style1.Ws);
            AssembledStyles style2 = clientRun2.UniformRunStyles(1);

            Assert.AreEqual(wsFrn, style2.Ws);
            Assert.AreEqual(0, clientRun2.UniformRunStart(0));
            Assert.AreEqual(part1.Length, clientRun2.UniformRunLength(0));
            Assert.AreEqual(part1.Length, clientRun2.UniformRunStart(1));
            Assert.AreEqual(part2.Length, clientRun2.UniformRunLength(1));
        }
Пример #3
0
        public void MlsDelete()
        {
            var styles = new AssembledStyles();
            var root   = new RootBoxFdo(styles.WithWs(23));
            var mock1  = new MockData1(23, 23);

            mock1.MlSimpleOne = new MultiAccessor(23, 23);
            mock1.MlSimpleOne.set_String(23, TsStrFactoryClass.Create().MakeString("This is it", 23));
            var engine = new FakeRenderEngine()
            {
                Ws = 23, SegmentHeight = 13
            };
            var factory = new FakeRendererFactory();

            factory.SetRenderer(23, engine);
            root.Builder.Show(Display.Of(() => mock1.MlSimpleOne, 23));
            var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);

            root.Layout(layoutArgs);
            PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
            MockSite       site   = new MockSite();

            site.m_transform  = ptrans;
            site.m_vwGraphics = m_gm.VwGraphics;
            root.Site         = site;

            SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is ".Length).Install();
            var sel = root.Selection as RangeSelection;

            // This is currently the main test for SelectionBuilder.In(RootBox) and SelectionBuilder.To in TsStrings
            // This verifies that it makes roughly the right range selection.
            Assert.That(sel.Anchor.LogicalParaPosition, Is.EqualTo("This ".Length));
            Assert.That(sel.DragEnd.LogicalParaPosition, Is.EqualTo("This is ".Length));

            Assert.That(sel.CanDelete(), Is.True);
            root.OnDelete();
            ITsString i = mock1.MlSimpleOne.get_String(23);

            Assert.That(mock1.MlSimpleOne.get_String(23).Text, Is.EqualTo("This it"));
            var ip = root.Selection as InsertionPoint;

            Assert.That(ip.LogicalParaPosition, Is.EqualTo("This ".Length));
            // Enhance JohnT: if there is any reason to prefer associatePrevious to be true or false,
            // clamp that and make it so.
            // A fairly rudimentary check on invalidate, since we elsewhere check general string-edit ops.
            Assert.That(site.RectsInvalidatedInRoot, Is.Not.Empty);
        }
Пример #4
0
        // Add to the root a text paragraph which reflects the SimpleText property.
        private void AddSimpleTextPara(AssembledStyles styles, int ws, RootBox root)
        {
            var items = new List <ClientRun>();
            var run   = new StringClientRun("This is the day that the Lord has made. We will rejoice and be glad in it",
                                            styles.WithWs(ws));

            items.Add(run);
            TextSource source = new TextSource(items);
            ParaBox    para   = new ParaBox(styles, source);
            var        hookup = new StringHookup(this, () => this.SimpleText,
                                                 hook => SimpleTextChanged += hook.StringPropChanged,
                                                 hook => SimpleTextChanged -= hook.StringPropChanged, para);

            hookup.Writer = newVal => SimpleText = newVal;
            run.Hookup    = hookup;
            root.AddBox(para);
        }
Пример #5
0
        public void Contains()
        {
            var styles   = new AssembledStyles();
            var runStyle = styles.WithWs(32);
            var root     = new RootBoxFdo(styles);
            var para1    = MakePara(styles, runStyle, "This is the day");
            var para2    = MakePara(styles, runStyle, "that the Lord has made");
            var para3    = MakePara(styles, runStyle, "We will rejoice");
            var div      = new DivBox(styles);
            var para4    = MakePara(styles, runStyle, "and be glad in it");
            var para5    = MakePara(styles, runStyle, "");
            var para6    = MakePara(styles, runStyle, "Rejoice!");

            root.AddBox(para1);
            root.AddBox(para2);
            div.AddBox(para3);
            div.AddBox(para4);
            root.AddBox(div);
            root.AddBox(para5);
            root.AddBox(para6);
            var run1       = para1.Source.ClientRuns[0] as StringClientRun;
            var ip1_0      = run1.SelectAt(para1, 0, false);
            var ip1_2p     = run1.SelectAt(para1, 2, true);
            var range1_0_2 = new RangeSelection(ip1_0, ip1_2p);

            Assert.That(range1_0_2.Contains(ip1_0), Is.True, "selection at start of range is included");
            Assert.That(range1_0_2.Contains(ip1_2p), Is.True, "selection at end of range is included");
            var ip1_1p = run1.SelectAt(para1, 1, true);

            Assert.That(range1_0_2.Contains(ip1_1p), Is.True, "selection in middle of 1-para range is included");
            var ip1_3p = run1.SelectAt(para1, 3, true);

            Assert.That(range1_0_2.Contains(ip1_3p), Is.False);
            var ip1_2a = run1.SelectAt(para1, 2, false);

            Assert.That(range1_0_2.Contains(ip1_2a), Is.False, "ip at end associated following is not included");

            var ip1_5p = run1.SelectAt(para1, 5, true);

            var range1_2_5 = new RangeSelection(ip1_2a, ip1_5p);

            Assert.That(range1_2_5.Contains(ip1_0), Is.False, "IP before start in same para not included");
            Assert.That(range1_2_5.Contains(ip1_2p), Is.False, "IP at start associated previous not included");
            Assert.That(range1_2_5.Contains(ip1_2a), Is.True, "IP at start not associated previous is included");

            var run2   = para2.Source.ClientRuns[0] as StringClientRun;
            var ip2_2p = run2.SelectAt(para2, 2, true);

            Assert.That(range1_2_5.Contains(ip2_2p), Is.False, "IP in following paragraph not included");

            var ip2_5p     = run2.SelectAt(para2, 5, true);
            var ip2_2a     = run2.SelectAt(para2, 2, false);
            var range2_5_2 = new RangeSelection(ip2_5p, ip2_2a);
            var ip2_3a     = run2.SelectAt(para2, 3, false);

            Assert.That(range2_5_2.Contains(ip2_3a), Is.True, "IP in middle of backwards selection is included");
            Assert.That(range2_5_2.Contains(ip1_2a), Is.False, "IP in previous para not included");

            var run6         = para6.Source.ClientRuns[0] as StringClientRun;
            var ip6_2p       = run6.SelectAt(para6, 2, true);
            var ip1_5a       = run1.SelectAt(para1, 5, false);
            var range1_5_6_2 = new RangeSelection(ip1_5a, ip6_2p);

            Assert.That(range1_5_6_2.Contains(ip1_0), Is.False, "IP before multi-para not included");
            Assert.That(range1_5_6_2.Contains(ip1_3p), Is.False, "IP before multi-para not included, even with offset > end offset");
            var ip6_4a = run6.SelectAt(para6, 4, false);

            Assert.That(range1_5_6_2.Contains(ip6_4a), Is.False, "IP after multi-para not included, even with offset < start offset");
            Assert.That(range1_5_6_2.Contains(ip2_3a), Is.True, "IP middle para of multi is included");

            var run4 = para4.Source.ClientRuns[0] as StringClientRun;
            var ip40 = run4.SelectAt(para4, 0, false);

            Assert.That(range1_5_6_2.Contains(ip40), Is.True, "IP in div within multi is included");

            var run5  = para5.Source.ClientRuns[0] as StringClientRun;
            var ip50a = run5.SelectAt(para5, 0, false);

            Assert.That(range1_5_6_2.Contains(ip50a), Is.True, "IP in empty para within multi is included");

            // I'm not absolutely sure this is the right design, but it's rather arbitrary whether an IP in an empty
            // paragraph associates forward or backward. If a range extends to the empty paragraph, I think it should
            // be included either way.
            var range1_5_5_0 = new RangeSelection(ip1_5a, ip50a);

            Assert.That(range1_5_5_0.Contains(ip50a), Is.True, "IP (ap false) in empty para at end of multi is included");
            var range5_0_6_2 = new RangeSelection(ip50a, ip6_2p);

            Assert.That(range5_0_6_2.Contains(ip50a), Is.True, "IP (ap false) in empty para at start of multi is included");
            var ip50p = run5.SelectAt(para5, 0, true);

            Assert.That(range1_5_5_0.Contains(ip50p), Is.True, "IP (ap true) in empty para at end of multi is included");
            Assert.That(range5_0_6_2.Contains(ip50p), Is.True, "IP (ap true) in empty para at end of multi is included");
        }
Пример #6
0
        public void RenderRuns()
        {
            string          part0      = "abc def";
            AssembledStyles styles     = new AssembledStyles().WithWs(wsEn);
            StringClientRun clientRun0 = new StringClientRun(part0, styles);
            var             clientRuns = new List <IClientRun>();

            clientRuns.Add(clientRun0);

            string          part0a      = " frn";
            StringClientRun clientRun0a = new StringClientRun(part0a, styles.WithWs(wsFrn));

            clientRuns.Add(clientRun0a);

            // Run 1
            string     part1 = " ghijk";        // english
            string     part2 = " lmno";         // french
            ITsString  tss   = tsf.MakeString(part1, wsEn);
            ITsStrBldr bldr  = tss.GetBldr();

            bldr.Replace(bldr.Length, bldr.Length, part2, ttpFrn);
            TssClientRun clientRun1 = new TssClientRun(bldr.GetString(), styles);

            clientRuns.Add(clientRun1);

            // Run 2a
            string    part2a    = " french insert";
            string    part2b    = " insert";       // english
            ITsString tssInsert = tsf.MakeString(part2b, wsEn);

            bldr = tssInsert.GetBldr();
            bldr.Replace(0, 0, part2a, ttpFrn);
            TssClientRun clientRun2b = new TssClientRun(bldr.GetString(), styles);

            clientRuns.Add(clientRun2b);

            // IRuntem 2
            string          part3      = " pq";
            string          part4      = "\xfffc";
            StringClientRun clientRun2 = new StringClientRun(part3 + part4, styles);

            clientRuns.Add(clientRun2);

            // Run 3
            string          part5      = "more french";
            string          part6      = "\xfffc";
            StringClientRun clientRun3 = new StringClientRun(part5 + part6, styles.WithWs(wsFrn));

            clientRuns.Add(clientRun3);

            // Run 4
            string          part7      = "English";
            StringClientRun clientRun4 = new StringClientRun(part7, styles.WithWs(wsFrn));

            clientRuns.Add(clientRun4);

            BlockBox box = new BlockBox(styles.WithWs(wsFrn), Color.Red, 72000, 36000);

            TextSource source = new TextSource(clientRuns, (run, offset) => (run == clientRun2 ? new StringClientRun(orcText, run.UniformRunStyles(0).WithWs(wsFrn)) : (IClientRun)box));

            List <IRenderRun> renderRuns = source.RenderRuns;

            VerifyRenderRun(renderRuns[0], 0, part0.Length, "first - en");
            int len = part0.Length;

            VerifyRenderRun(renderRuns[1], len, part0a.Length, "0a - frn");
            len += part0a.Length;
            VerifyRenderRun(renderRuns[2], len, part1.Length, "part1 - en");
            len += part1.Length;
            VerifyRenderRun(renderRuns[3], len, part2.Length + part2a.Length, "part2 & 2a (french)");
            len += part2.Length + part2a.Length;
            VerifyRenderRun(renderRuns[4], len, part2b.Length + part3.Length, "2b and 2 (Eng)");
            len += part2b.Length + part3.Length;
            VerifyRenderRun(renderRuns[5], len, orcText.Length + part5.Length, "orc + other french");
            len += orcText.Length + part5.Length;
            VerifyRenderRun(renderRuns[6], len, 1, "single box");
            len += 1;
            VerifyRenderRun(renderRuns[7], len, part7.Length, "run with same props as preceding box");
            Assert.AreEqual(8, renderRuns.Count);
        }
Пример #7
0
		public void MlsRuns()
		{
			string part1 = "abc def";
			IViewMultiString mls = new MultiAccessor(wsEn, wsEn);
			mls.set_String(wsEn, tsf.MakeString(part1, wsEn));
			AssembledStyles styles = new AssembledStyles();
			MlsClientRun clientRun = new MlsClientRun(mls, styles.WithWs(wsEn));
			Assert.AreEqual(1, clientRun.UniformRunCount);
			Assert.AreEqual(part1, clientRun.UniformRunText(0));
			AssembledStyles style1 = clientRun.UniformRunStyles(0);
			Assert.AreEqual(wsEn, style1.Ws);
			Assert.AreEqual(0, clientRun.UniformRunStart(0));
			Assert.AreEqual(part1.Length, clientRun.UniformRunLength(0));

			string part2 = " ghi";
			ITsStrBldr bldr = mls.get_String(wsEn).GetBldr();
			bldr.Replace(part1.Length, part1.Length, part2, ttpFrn);
			IViewMultiString multibldr = new MultiAccessor(wsEn, wsEn);
			multibldr.set_String(wsFrn, bldr.GetString());
			MlsClientRun clientRun2 = new MlsClientRun(multibldr, styles.WithWs(wsFrn));
			Assert.AreEqual(2, clientRun2.UniformRunCount);
			Assert.AreEqual(part1, clientRun2.UniformRunText(0));
			Assert.AreEqual(part2, clientRun2.UniformRunText(1));
			style1 = clientRun2.UniformRunStyles(0);
			Assert.AreEqual(wsEn, style1.Ws);
			AssembledStyles style2 = clientRun2.UniformRunStyles(1);
			Assert.AreEqual(wsFrn, style2.Ws);
			Assert.AreEqual(0, clientRun2.UniformRunStart(0));
			Assert.AreEqual(part1.Length, clientRun2.UniformRunLength(0));
			Assert.AreEqual(part1.Length, clientRun2.UniformRunStart(1));
			Assert.AreEqual(part2.Length, clientRun2.UniformRunLength(1));
		}
Пример #8
0
		public void RenderRuns()
		{
			string part0 = "abc def";
			AssembledStyles styles = new AssembledStyles().WithWs(wsEn);
			StringClientRun clientRun0 = new StringClientRun(part0, styles);
			var clientRuns = new List<IClientRun>();
			clientRuns.Add(clientRun0);

			string part0a = " frn";
			StringClientRun clientRun0a = new StringClientRun(part0a, styles.WithWs(wsFrn));
			clientRuns.Add(clientRun0a);

			// Run 1
			string part1 = " ghijk"; // english
			string part2 = " lmno"; // french
			ITsString tss = tsf.MakeString(part1, wsEn);
			ITsStrBldr bldr = tss.GetBldr();
			bldr.Replace(bldr.Length, bldr.Length, part2, ttpFrn);
			TssClientRun clientRun1 = new TssClientRun(bldr.GetString(), styles);
			clientRuns.Add(clientRun1);

			// Run 2a
			string part2a = " french insert";
			string part2b = " insert"; // english
			ITsString tssInsert = tsf.MakeString(part2b, wsEn);
			bldr = tssInsert.GetBldr();
			bldr.Replace(0, 0, part2a, ttpFrn);
			TssClientRun clientRun2b = new TssClientRun(bldr.GetString(), styles);
			clientRuns.Add(clientRun2b);

			// IRuntem 2
			string part3 = " pq";
			string part4 = "\xfffc";
			StringClientRun clientRun2 = new StringClientRun(part3 + part4, styles);
			clientRuns.Add(clientRun2);

			// Run 3
			string part5 = "more french";
			string part6 = "\xfffc";
			StringClientRun clientRun3 = new StringClientRun(part5 + part6, styles.WithWs(wsFrn));
			clientRuns.Add(clientRun3);

			// Run 4
			string part7 = "English";
			StringClientRun clientRun4 = new StringClientRun(part7, styles.WithWs(wsFrn));
			clientRuns.Add(clientRun4);

			BlockBox box = new BlockBox(styles.WithWs(wsFrn), Color.Red, 72000, 36000);

			TextSource source = new TextSource(clientRuns, (run, offset) => (run == clientRun2 ? new StringClientRun(orcText, run.UniformRunStyles(0).WithWs(wsFrn)) : (IClientRun)box));

			List<IRenderRun> renderRuns = source.RenderRuns;
			VerifyRenderRun(renderRuns[0], 0, part0.Length, "first - en");
			int len = part0.Length;
			VerifyRenderRun(renderRuns[1], len, part0a.Length, "0a - frn");
			len += part0a.Length;
			VerifyRenderRun(renderRuns[2], len, part1.Length, "part1 - en");
			len += part1.Length;
			VerifyRenderRun(renderRuns[3], len, part2.Length + part2a.Length, "part2 & 2a (french)");
			len += part2.Length + part2a.Length;
			VerifyRenderRun(renderRuns[4], len, part2b.Length + part3.Length, "2b and 2 (Eng)");
			len += part2b.Length + part3.Length;
			VerifyRenderRun(renderRuns[5], len, orcText.Length + part5.Length, "orc + other french");
			len += orcText.Length + part5.Length;
			VerifyRenderRun(renderRuns[6], len, 1, "single box");
			len += 1;
			VerifyRenderRun(renderRuns[7], len, part7.Length, "run with same props as preceding box");
			Assert.AreEqual(8, renderRuns.Count);

		}
Пример #9
0
		public void OrcBoxRun()
		{
			// Run 0
			string part0 = "abc";
			string part1 = "\xfffc";
			string part2 = "defg";

			AssembledStyles styles = new AssembledStyles().WithWs(wsEn);
			StringClientRun clientRun0 = new StringClientRun(part0+part1+part2, styles);
			var clientRuns = new List<IClientRun>();
			clientRuns.Add(clientRun0);

			BlockBox box = new BlockBox(styles.WithWs(wsFrn), Color.Red, 72000, 36000);

			TextSource source = new TextSource(clientRuns, (run, offset) => box);

			MapRun[] runs = source.Runs;
			Assert.AreEqual(3, runs.Length);
			VerifyRun(0, clientRun0, 0, 0, part0, runs[0], "first run of complex source with box");
			int len = part0.Length;
			VerifyRun(len, box, len, part0.Length, part1, runs[1], "2nd run of complex source with box");
			len += 1;
			VerifyRun(len, clientRun0, len, part0.Length+1, part2, runs[2], "3rd run of complex source with box");
			len += part2.Length;
			Assert.AreEqual(len, source.Length, "length of complex source with box");
			VerifyCharProps(source, part0.Length, wsFrn, part0.Length, part0.Length + 1, "props of box");
		}
Пример #10
0
		public void MlsDelete()
		{
			var styles = new AssembledStyles();
			var root = new RootBoxFdo(styles.WithWs(23));
			var mock1 = new MockData1(23, 23);
			mock1.MlSimpleOne = new MultiAccessor(23, 23);
			mock1.MlSimpleOne.set_String(23, TsStrFactoryClass.Create().MakeString("This is it", 23));
			var engine = new FakeRenderEngine() { Ws = 23, SegmentHeight = 13 };
			var factory = new FakeRendererFactory();
			factory.SetRenderer(23, engine);
			root.Builder.Show(Display.Of(() => mock1.MlSimpleOne, 23));
			var layoutArgs = MakeLayoutInfo(Int32.MaxValue / 2, m_gm.VwGraphics, factory);
			root.Layout(layoutArgs);
			PaintTransform ptrans = new PaintTransform(2, 2, 96, 96, 0, 0, 96, 96);
			MockSite site = new MockSite();
			site.m_transform = ptrans;
			site.m_vwGraphics = m_gm.VwGraphics;
			root.Site = site;

			SelectionBuilder.In(root).Offset("This ".Length).To.Offset("This is ".Length).Install();
			var sel = root.Selection as RangeSelection;
			// This is currently the main test for SelectionBuilder.In(RootBox) and SelectionBuilder.To in TsStrings
			// This verifies that it makes roughly the right range selection.
			Assert.That(sel.Anchor.LogicalParaPosition, Is.EqualTo("This ".Length));
			Assert.That(sel.DragEnd.LogicalParaPosition, Is.EqualTo("This is ".Length));

			Assert.That(sel.CanDelete(), Is.True);
			root.OnDelete();
			ITsString i = mock1.MlSimpleOne.get_String(23);
			Assert.That(mock1.MlSimpleOne.get_String(23).Text, Is.EqualTo("This it"));
			var ip = root.Selection as InsertionPoint;
			Assert.That(ip.LogicalParaPosition, Is.EqualTo("This ".Length));
			// Enhance JohnT: if there is any reason to prefer associatePrevious to be true or false,
			// clamp that and make it so.
			// A fairly rudimentary check on invalidate, since we elsewhere check general string-edit ops.
			Assert.That(site.RectsInvalidatedInRoot, Is.Not.Empty);
		}
Пример #11
0
		public void Contains()
		{
			var styles = new AssembledStyles();
			var runStyle = styles.WithWs(32);
			var root = new RootBoxFdo(styles);
			var para1 = MakePara(styles, runStyle, "This is the day");
			var para2 = MakePara(styles, runStyle, "that the Lord has made");
			var para3 = MakePara(styles, runStyle, "We will rejoice");
			var div = new DivBox(styles);
			var para4 = MakePara(styles, runStyle, "and be glad in it");
			var para5 = MakePara(styles, runStyle, "");
			var para6 = MakePara(styles, runStyle, "Rejoice!");
			root.AddBox(para1);
			root.AddBox(para2);
			div.AddBox(para3);
			div.AddBox(para4);
			root.AddBox(div);
			root.AddBox(para5);
			root.AddBox(para6);
			var run1 = para1.Source.ClientRuns[0] as StringClientRun;
			var ip1_0 = run1.SelectAt(para1, 0, false);
			var ip1_2p = run1.SelectAt(para1, 2, true);
			var range1_0_2 = new RangeSelection(ip1_0, ip1_2p);
			Assert.That(range1_0_2.Contains(ip1_0), Is.True, "selection at start of range is included");
			Assert.That(range1_0_2.Contains(ip1_2p), Is.True, "selection at end of range is included");
			var ip1_1p = run1.SelectAt(para1, 1, true);
			Assert.That(range1_0_2.Contains(ip1_1p), Is.True, "selection in middle of 1-para range is included");
			var ip1_3p = run1.SelectAt(para1, 3, true);
			Assert.That(range1_0_2.Contains(ip1_3p), Is.False);
			var ip1_2a = run1.SelectAt(para1, 2, false);
			Assert.That(range1_0_2.Contains(ip1_2a), Is.False, "ip at end associated following is not included");

			var ip1_5p = run1.SelectAt(para1, 5, true);

			var range1_2_5 = new RangeSelection(ip1_2a, ip1_5p);
			Assert.That(range1_2_5.Contains(ip1_0), Is.False, "IP before start in same para not included");
			Assert.That(range1_2_5.Contains(ip1_2p), Is.False, "IP at start associated previous not included");
			Assert.That(range1_2_5.Contains(ip1_2a), Is.True, "IP at start not associated previous is included");

			var run2 = para2.Source.ClientRuns[0] as StringClientRun;
			var ip2_2p = run2.SelectAt(para2, 2, true);
			Assert.That(range1_2_5.Contains(ip2_2p), Is.False, "IP in following paragraph not included");

			var ip2_5p = run2.SelectAt(para2, 5, true);
			var ip2_2a = run2.SelectAt(para2, 2, false);
			var range2_5_2 = new RangeSelection(ip2_5p, ip2_2a);
			var ip2_3a = run2.SelectAt(para2, 3, false);
			Assert.That(range2_5_2.Contains(ip2_3a), Is.True, "IP in middle of backwards selection is included");
			Assert.That(range2_5_2.Contains(ip1_2a), Is.False, "IP in previous para not included");

			var run6 = para6.Source.ClientRuns[0] as StringClientRun;
			var ip6_2p = run6.SelectAt(para6, 2, true);
			var ip1_5a = run1.SelectAt(para1, 5, false);
			var range1_5_6_2 = new RangeSelection(ip1_5a, ip6_2p);
			Assert.That(range1_5_6_2.Contains(ip1_0), Is.False, "IP before multi-para not included");
			Assert.That(range1_5_6_2.Contains(ip1_3p), Is.False, "IP before multi-para not included, even with offset > end offset");
			var ip6_4a = run6.SelectAt(para6, 4, false);
			Assert.That(range1_5_6_2.Contains(ip6_4a), Is.False, "IP after multi-para not included, even with offset < start offset");
			Assert.That(range1_5_6_2.Contains(ip2_3a), Is.True, "IP middle para of multi is included");

			var run4 = para4.Source.ClientRuns[0] as StringClientRun;
			var ip40 = run4.SelectAt(para4, 0, false);
			Assert.That(range1_5_6_2.Contains(ip40), Is.True, "IP in div within multi is included");

			var run5 = para5.Source.ClientRuns[0] as StringClientRun;
			var ip50a = run5.SelectAt(para5, 0, false);
			Assert.That(range1_5_6_2.Contains(ip50a), Is.True, "IP in empty para within multi is included");

			// I'm not absolutely sure this is the right design, but it's rather arbitrary whether an IP in an empty
			// paragraph associates forward or backward. If a range extends to the empty paragraph, I think it should
			// be included either way.
			var range1_5_5_0 = new RangeSelection(ip1_5a, ip50a);
			Assert.That(range1_5_5_0.Contains(ip50a), Is.True, "IP (ap false) in empty para at end of multi is included");
			var range5_0_6_2 = new RangeSelection(ip50a, ip6_2p);
			Assert.That(range5_0_6_2.Contains(ip50a), Is.True, "IP (ap false) in empty para at start of multi is included");
			var ip50p = run5.SelectAt(para5, 0, true);
			Assert.That(range1_5_5_0.Contains(ip50p), Is.True, "IP (ap true) in empty para at end of multi is included");
			Assert.That(range5_0_6_2.Contains(ip50p), Is.True, "IP (ap true) in empty para at end of multi is included");
		}