3 using System.Collections;
4 using System.Collections.Generic;
11 public enum MTextFormat
13 MTEXT_FORMAT_US_ASCII,
15 MTEXT_FORMAT_UTF_16BE,
16 MTEXT_FORMAT_UTF_16LE,
17 MTEXT_FORMAT_UTF_32BE,
18 MTEXT_FORMAT_UTF_32LE,
22 public class MProperty
29 /// A text inserted before a character that has this property
30 /// inherits this property. If the text already has properties
31 /// of the same key, they are deleted at first.
34 /// A text inserted after a character that has this property
35 /// inherits this property. If the text already has properties
36 /// of the same key, they are deleted at first.
39 /// This property is deleted from a span of text if the span is
40 /// modified (i.e. a character is changed, a text is inserted,
41 /// some part is deleted). This property is also deleted if a
42 /// property of the same key is added, which means that this
43 /// property is not stackable. In addition this property is
44 /// never merged with the same value of preceding or following
48 /// Like Sensitive but also this property is deleted from a span
49 /// of text if a text just before the span is modified,
50 /// inserted, or deleted.
51 FrontSensitive = 0x0C,
53 /// Like Sensitive but also this property is deleted from a span
54 /// of text if a text just after the span is modified, inserted,
62 public MSymbol Key { get { return key; } }
63 public object Val { get { return val; } }
65 public MProperty (MSymbol key, object val)
67 if (key.flags == null)
68 key.flags = Flags.None;
73 public MProperty (string name, object val)
75 key = MSymbol.PropertyKey (name);
79 public static bool HasFlags (MSymbol key, Flags flags)
81 return ((key.flags & flags) != Flags.None);
84 public override string ToString ()
86 return key.ToString () + ":" + val;
90 public class MText : IEnumerable, IEquatable<MText>, IComparable<MText>
93 public enum MTextFormat format;
95 private StringBuilder sb;
97 private int cache_pos;
98 private int cache_idx;
99 private MPlist intervals;
100 private MPlist default_property;
101 private bool read_only;
103 private static UTF8Encoding utf8 = new UTF8Encoding ();
105 private static int count_chars (String str)
107 int len = str.Length, n = 0;
109 for (int i = 0; i < len; i++, n++)
110 if (surrogate_high_p (str[i]))
115 private static int count_chars (StringBuilder str)
117 int len = str.Length, n = 0;
119 for (int i = 0; i < len; i++, n++)
120 if (surrogate_high_p (str[i]))
127 sb = new StringBuilder ();
128 intervals = new MPlist ();
131 public MText (byte[] str)
133 sb = new StringBuilder (utf8.GetString (str));
134 nchars = count_chars (sb);
135 intervals = new MPlist ();
138 public MText (String str)
140 sb = new StringBuilder (str);
141 nchars = count_chars (str);
142 intervals = new MPlist ();
145 public MText (StringBuilder str)
148 nchars = count_chars (str);
149 intervals = new MPlist ();
152 public static MText operator+ (object obj, MText mt)
156 MText mtnew = new MText ((string) obj);
157 return mtnew.Ins (mtnew.Length, mt);
159 throw new Exception ("Unknown object type: " + obj.GetType());
162 public static MText operator+ (MText mt, object obj)
165 return mt + new MText ((string) obj);
167 return mt.Dup ().Ins (mt.Length, (int) obj);
169 return mt.Dup ().Ins (mt.Length, (int) ((char) obj));
170 throw new Exception ("Unknown object type: " + obj.GetType());
173 public static MText operator+ (MText mt1, MText mt2)
175 return mt1.Dup ().Ins (mt1.Length, mt2);
179 public bool ReadOnly { get { return read_only; } }
180 public int Length { get { return nchars; } }
184 // for IEnumerable interface
185 public IEnumerator GetEnumerator() { return new MTextEnum (this); }
187 // for IEquatable interface
188 public bool Equals (MText other) { return this.sb.Equals (other.sb); }
190 // for IComparable interface
191 public int CompareTo (MText other)
193 return this.sb.ToString ().CompareTo (other.sb.ToString ());
196 public override string ToString () { return sb.ToString (); }
198 private static bool surrogate_high_p (char c)
200 return (c >= 0xD800 && c < 0xDC00);
203 private static bool surrogate_low_p (char c)
205 return (c >= 0xDC00 && c < 0xE000);
208 private static int inc_idx (StringBuilder sb, int i)
210 return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
213 private static int dec_idx (StringBuilder sb, int i)
215 return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
218 private static int pos_to_idx (MText mt, int pos)
220 if (pos == mt.cache_pos)
226 if (pos < mt.cache_pos)
228 if (mt.cache_pos == mt.cache_idx)
230 if (pos < mt.cache_pos - pos)
237 p = mt.cache_pos; i = mt.cache_idx;
243 if (mt.nchars - mt.cache_pos == mt.sb.Length - mt.cache_idx)
244 return (mt.cache_idx + pos - mt.cache_pos);
245 if (pos - mt.cache_pos < mt.nchars - pos)
247 p = mt.cache_pos; i = mt.cache_idx;
252 p = mt.nchars; i = mt.sb.Length;
257 for (; p < pos; i = inc_idx (mt.sb, i), p++);
259 for (; p > pos; i = dec_idx (mt.sb, i), p--);
265 private void check_pos (int pos, bool tail_ok)
267 if (pos < 0 || (tail_ok ? pos > nchars : pos >= nchars))
268 throw new Exception ("Invalid MText position:" + pos);
271 private bool check_range (int from, int to, bool zero_ok)
273 if (from < 0 || (zero_ok ? from > to : from >= to)
275 throw new Exception ("Invalid MText range");
279 private void insert (int pos, MText mt2, int from, int to)
281 check_pos (pos, true);
285 Console.Write ("inserting {0} to {1} of ", from, to);
286 mt2.DumpPropNested ();
290 foreach (MPlist plist in intervals)
292 MInterval root = (MInterval) plist.Val;
293 MPlist p = mt2.intervals.Find (plist.Key);
294 MInterval i = p == null ? null : (MInterval) p.Val;
296 root.Insert (pos, i, from, to);
298 foreach (MPlist plist in mt2.intervals)
299 if (intervals.Find (plist.Key) == null)
304 root = ((MInterval) plist.Val).Copy (this, from, to);
307 root = new MInterval (plist.Key, this);
308 root.Insert (pos, (MInterval) plist.Val, from, to);
310 intervals.Push (plist.Key, root);
313 int pos_idx = pos_to_idx (this, pos);
314 int from_idx = pos_to_idx (mt2, from);
315 int to_idx = pos_to_idx (mt2, to);
317 sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
321 private void insert (int pos, int c)
323 check_pos (pos, true);
325 int pos_idx = pos_to_idx (this, pos);
330 sb.Insert (pos_idx, ch);
334 char high = (char) (0xD800 + ((c - 0x10000) >> 10));
335 char low = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
336 sb.Insert (pos_idx, low);
337 sb.Insert (pos_idx, high);
340 foreach (MPlist plist in intervals)
341 ((MInterval) plist.Val).Insert (pos, null, 0, 1);
344 public int this[int i]
347 i = pos_to_idx (this, i);
350 if (surrogate_high_p (sb[i]))
352 sb[i] = (char) value;
356 char high = (char) (0xD800 + ((value - 0x10000) >> 10));
357 char low = (char) (0xDC00 + ((value - 0x10000) & 0x3FF));
359 if (! surrogate_high_p (sb[i]))
366 i = pos_to_idx (this, i);
367 return (surrogate_high_p (sb[i])
368 ? ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
375 MText mt = new MText (sb.ToString ());
377 foreach (MPlist p in intervals)
378 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, 0, Length));
382 public MText Dup (int from, int to)
384 if (check_range (from, to, true))
386 int from_idx = pos_to_idx (this, from);
387 int len = pos_to_idx (this, to) - from_idx;
388 MText mt = new MText (sb.ToString ().Substring (from_idx, len));
390 foreach (MPlist p in intervals)
391 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, from, to));
395 public MText Ins (int pos, int c)
401 public MText Ins (int pos, MText mt)
403 insert (pos, mt, 0, mt.nchars);
407 public MText Ins (int pos, MText mt, int from, int to)
409 insert (pos, mt, from, to);
413 public MText Cat (int c)
419 public MText Del (int from, int to)
421 if (check_range (from, to, true))
424 sb.Remove (from, pos_to_idx (this, to) - pos_to_idx (this, from));
428 foreach (MPlist plist in intervals)
430 MInterval root = (MInterval) plist.Val;
431 root.Delete (from, to);
432 if (from > 0 && from < nchars)
433 ((MInterval) plist.Val).MergeAfterChange (from, from);
442 public object GetProp (int pos, MSymbol key)
444 check_pos (pos, false);
446 MInterval i = (MInterval) intervals.Get (key);
450 MProperty prop = i.Get (pos);
451 return (prop != null ? prop.Val : null);
454 public object GetProp (int pos, MSymbol key, out MProperty prop)
456 check_pos (pos, false);
458 MInterval i = (MInterval) intervals.Get (key);
460 return (prop = null);
462 return (prop != null ? prop.Val : null);
465 public object GetProp (int pos, MSymbol key, out MProperty[] array)
467 check_pos (pos, false);
469 MInterval i = (MInterval) intervals.Get (key);
471 return (array = null);
472 MProperty prop = i.Get (pos, out array);
473 return (prop != null ? prop.Val : null);
476 public void PushProp (int from, int to, MSymbol key, object val)
478 if (! check_range (from, to, true))
479 PushProp (from, to, new MProperty (key, val));
482 public void PushProp (int from, int to, MProperty prop)
486 if (default_property == null)
487 default_property = new MPlist ();
488 default_property.Push (prop.key, prop.val);
492 if (check_range (from, to, true))
495 MPlist p = intervals.Find (prop.key);
500 root = new MInterval (prop.key, this);
501 intervals.Push (prop.key, root);
504 root = (MInterval) p.Val;
506 if (root.isSensitive)
507 root.PopSensitive (from, to);
508 root.Push (from, to, prop);
509 root.MergeAfterChange (from, to);
514 public void PopProp (int from, int to, MSymbol key)
518 if (default_property == null)
520 MPlist p = default_property.Find (key);
527 if (check_range (from, to, true))
530 MPlist p = intervals.Find (key);
534 MInterval root = (MInterval) p.Val;
535 if (root.isSensitive)
536 root.PopSensitive (from, to);
539 root = (MInterval) p.Val;
542 root.MergeAfterChange (from, to);
548 public void DumpProp ()
551 foreach (MPlist p in intervals)
552 ((MInterval) p.Val).Dump (true);
553 Console.WriteLine (")");
556 public void DumpPropNested ()
558 Console.WriteLine ("total length = {0}", Length);
559 foreach (MPlist p in intervals)
560 ((MInterval) p.Val).DumpNested (true);
563 private class MInterval
565 // position: 0 1 2 3 4 5 6 7
566 // | A | B | C | D | E F | G |
567 // interval |---|---|---|<->|-------|---|
568 // |---|<->|---| |<----->|---|
572 // [3 (1 2)] [3 (4 6)]
573 // [1 (0 1)] [2 (2 3)] [1 (6 7)]
575 private static int count = 0;
578 private int From, To;
580 private MPlist Stack;
581 private MInterval Left, Right, Parent;
584 public MInterval (MSymbol key, MText mt, int length)
587 throw new Exception ("Invalid interval length");
591 Stack = new MPlist ();
595 public MInterval (MSymbol key, MText mt)
599 Length = mt.sb.Length;
602 Stack = new MPlist ();
606 /// POS must be smaller than Length;
607 public MProperty Get (int pos)
609 MInterval i = find_head (pos);
611 return (i.Stack.IsEmpty ? null : (MProperty) i.Stack.Val);
614 /// POS must be smaller than Length;
615 public MProperty Get (int pos, out MProperty[] array)
617 MInterval i = find_head (pos);
626 array = new MProperty[i.Stack.Count];
630 for (idx = 0, p = i.Stack; ! p.IsEmpty; idx++, p = p.Next)
631 array[idx] = (MProperty) p.Val;
635 private MInterval (MSymbol key, MText mt, int length, MPlist stack)
642 Stack = stack == null ? new MPlist () : stack.Clone ();
646 private bool isRearSticky
648 get { return MProperty.HasFlags (Key, MProperty.Flags.RearSticky) ; }
651 private bool isFrontSticky
653 get { return MProperty.HasFlags (Key, MProperty.Flags.FrontSticky) ; }
656 public bool isSensitive
658 get { return MProperty.HasFlags (Key, MProperty.Flags.Sensitive) ; }
661 public bool isFrontSensitive
663 get { return MProperty.HasFlags (Key,
664 MProperty.Flags.FrontSensitive) ; }
667 public bool isRearSensitive
669 get { return MProperty.HasFlags (Key,
670 MProperty.Flags.RearSensitive) ; }
673 private void update_from_to ()
678 To = Length - RightLength;
680 else if (Parent.Left == this)
682 From = Parent.From - Length + LeftLength;
683 To = Parent.From - RightLength;
687 From = Parent.To + LeftLength;
688 To = Parent.To + Length - RightLength;
692 private int LeftLength
694 get { return (Left == null ? 0 : Left.Length); }
697 private int RightLength
699 get { return (Right == null ? 0 : Right.Length); }
702 private MInterval LeftMost
708 return Left.LeftMost;
712 private MInterval RightMost
718 return Right.RightMost;
722 private MInterval Prev {
728 for (i = Left; i.Right != null; i = i.Right)
734 MInterval child = this;
735 for (i = Parent; i != null && i.Left == child;
736 child = i, i = i.Parent);
742 private MInterval Next {
748 for (i = Right; i.Left != null; i = i.Left)
754 MInterval child = this;
755 for (i = Parent; i != null && i.Right == child;
756 child = i, i = i.Parent);
762 private MInterval find_head (int pos)
766 return Left.find_head (pos);
768 return Right.find_head (pos);
772 private MInterval find_tail (int pos)
776 return Left.find_tail (pos);
778 return Right.find_tail (pos);
782 private bool mergeable (MInterval i)
786 for (p1 = Stack, p2 = i.Stack; ! p1.IsEmpty && ! p2.IsEmpty;
787 p1 = p1.Next, p2 = p2.Next)
788 if (p1.Val != p2.Val)
790 return (p1.IsEmpty && p2.IsEmpty);
793 // p-. or .-p p-. or .-p
794 // .-this-. .-right-.
795 // left .-right-. -> .-this-. c2
797 private MInterval promote_right ()
799 MInterval c1 = Right.Left;
803 mtext.intervals.Put (Key, Right);
804 else if (Parent.Left == this)
807 Parent.Right = Right;
810 Right.Parent = Parent;
812 Right.Length += LeftLength + (To - From);
817 Length = LeftLength + (To - From) + RightLength;
819 // Update C1 if necessary.
823 Parent.update_from_to ();
827 // p-. or .-p p-. or .-p
829 // .-left-. .-right-. -> c1 .-this-.
831 private MInterval promote_left ()
833 MInterval c2 = Left.Right;
837 mtext.intervals.Put (Key, Left);
838 else if (Parent.Left == this)
844 Left.Parent = Parent;
846 Left.Length += (To - From) + RightLength;
851 Length = LeftLength + (To - From) + RightLength;
853 // Update C2 if necessary.
857 Parent.update_from_to ();
861 public MInterval Balance ()
869 // .-left-. .-right-.
871 int diff = i.LeftLength - i.RightLength;
876 new_diff = (i.Length - i.LeftLength
877 + i.Left.RightLength - i.Left.LeftLength);
878 if (Math.Abs (new_diff) >= diff)
880 M17n.DebugPrint ("balancing #{0} by promoting left...", i.ID);
881 i = i.promote_left ();
882 M17n.DebugPrint ("done\n");
887 new_diff = (i.Length - i.RightLength
888 + i.Right.LeftLength - i.Right.RightLength);
889 if (Math.Abs (new_diff) >= diff)
891 M17n.DebugPrint ("balancing #{0} by promoting right\n", i.ID);
892 i = i.promote_right ();
901 public MInterval Copy (MText mt, int start, int end)
903 MInterval copy, left_copy = null, right_copy = null;
910 return Left.Copy (mt, start, end);
911 left_copy = Left.Copy (mt, start, From);
916 return Right.Copy (mt, start, end);
917 right_copy = Right.Copy (mt, To, end);
920 copy = new MInterval (Key, null, end - start, Stack);
922 if (isSensitive && (From < start || end < To))
924 if (left_copy != null)
926 copy.Left = left_copy;
927 left_copy.Parent = copy;
929 if (right_copy != null)
931 copy.Right = right_copy;
932 right_copy.Parent = copy;
937 public MInterval Copy (MText mt, int start, int end,
938 bool first, bool last)
940 MInterval copy = Copy (mt, start, end);
941 MInterval head = find_head (start);
942 MInterval tail = find_tail (end);
944 if (! head.Stack.IsEmpty
945 && ((isSensitive || isFrontSensitive) && head.From < start
946 || isFrontSensitive && ! first))
948 head = copy.find_head (0);
951 if (! tail.Stack.IsEmpty
952 && ((isSensitive || isRearSensitive) && end < head.To
953 || isRearSensitive && ! last))
955 tail = copy.find_tail (copy.Length);
958 M17n.DebugPrint ("Copied: {0}\n", copy);
965 private MInterval divide_right (int pos)
967 MInterval interval = new MInterval (Key, mtext, To - pos, Stack);
969 M17n.DebugPrint ("divide-right({0}) at {1}\n", pos, this);
973 interval.Right = Right;
974 Right.Parent = interval;
975 interval.Length += Right.Length;
977 interval.Parent = this;
985 private MInterval divide_left (int pos)
987 MInterval interval = new MInterval (Key, mtext, pos - From, Stack);
989 M17n.DebugPrint ("divide-left({0}) at {1}\n", pos, this);
993 interval.Left = Left;
994 Left.Parent = interval;
995 interval.Length += Left.Length;
997 interval.Parent = this;
1002 private void set_mtext (MText mt)
1006 Left.set_mtext (mt);
1008 Right.set_mtext (mt);
1011 private void enlarge (int len)
1015 for (MInterval prev = this, i = this.Parent; i != null;
1016 prev = i, i = i.Parent)
1027 private int graft_forward (MInterval interval, int start, int end)
1031 if (! Stack.IsEmpty && isRearSticky)
1033 else if (interval == null)
1034 len = Stack.IsEmpty ? end - start : 0;
1037 MInterval i = interval.find_head (start);
1041 && (isFrontSensitive
1042 || ((isSensitive || isRearSensitive) && i.From < start)))
1044 M17n.DebugPrint (" grafting {0}", i);
1051 while (i != null && i.From < end && mergeable (i))
1053 M17n.DebugPrint (" grafting {0}", i);
1054 len += i.To - i.From;
1056 len -= start - i.From;
1066 M17n.DebugPrint (" grafted {0} in {1}\n", len, this);
1072 private int graft_backward (MInterval interval, int start, int end)
1076 if (! Stack.IsEmpty && isFrontSticky)
1078 else if (interval == null)
1079 len = Stack.IsEmpty ? end - start : 0;
1082 MInterval i = interval.find_tail (end);
1087 || ((isSensitive || isFrontSensitive) && end < i.To)))
1089 M17n.DebugPrint (" grafting {0}", i);
1090 if (i.From <= start)
1096 while (i != null && i.To <= start && mergeable (i))
1098 M17n.DebugPrint (" grafting {0}", i);
1099 len += i.To - i.From;
1102 if (i.From <= start)
1104 len -= start - i.From;
1111 M17n.DebugPrint (" grafted {0} in {1}\n", len, this);
1117 public void Insert (int pos, MInterval interval, int start, int end)
1121 M17n.DebugPrint ("insert({0} to {1}) at {2} in {3}",
1122 start, end, pos, this);
1125 Left.Insert (pos, interval, start, end);
1126 else if (pos == From)
1128 MInterval prev = Left != null ? Prev : null;
1130 if (isFrontSensitive)
1132 if (prev != null && isRearSensitive)
1133 prev.Stack.Clear ();
1134 if (prev != null && isRearSticky && ! prev.Stack.IsEmpty)
1136 prev.enlarge (end - start);
1139 if (isFrontSticky && ! Stack.IsEmpty)
1141 enlarge (end - start);
1144 bool front_grafted = false, rear_grafted = false;
1147 && (grafted = prev.graft_forward (interval, start, end)) > 0)
1152 front_grafted = true;
1154 if ((grafted = graft_backward (interval, start, end)) > 0)
1159 rear_grafted = true;
1162 if (interval != null)
1163 interval = interval.Copy (mtext, start, end,
1165 || (prev == null && start == 0)),
1168 interval = new MInterval (Key, mtext, end - start, null);
1173 // .-this-. ==> .-this-.
1185 interval.Parent = i;
1186 for (; i != null; i = i.Parent)
1187 i.Length += interval.Length;
1191 if (! Stack.IsEmpty)
1193 if (isSensitive || isFrontSensitive || isRearSensitive)
1195 else if (isFrontSticky || isRearSticky)
1197 enlarge (end - start);
1201 bool front_grafted = false, rear_grafted = false;
1203 if ((grafted = graft_forward (interval, start, end)) > 0)
1208 front_grafted = true;
1211 if ((grafted = graft_backward (interval, start, end)) > 0)
1216 rear_grafted = true;
1218 if (interval != null)
1219 interval = interval.Copy (mtext, start, end,
1220 front_grafted, rear_grafted);
1222 interval = new MInterval (Key, mtext, end - start, null);
1225 Right.Left = interval;
1226 interval.Parent = Right;
1227 for (MInterval i = Right; i != null; i = i.Parent)
1228 i.Length += interval.Length;
1232 MInterval next = Right != null ? Next : null;
1234 if (isRearSensitive)
1236 if (next != null && isFrontSensitive)
1237 next.Stack.Clear ();
1238 if (isRearSticky && ! Stack.IsEmpty)
1240 enlarge (end - start);
1243 if (next != null && isFrontSticky && ! next.Stack.IsEmpty)
1245 next.enlarge (end - start);
1248 bool front_grafted = false, rear_grafted = false;
1251 && (grafted = next.graft_backward (interval, start, end)) > 0)
1256 rear_grafted = true;
1258 if ((grafted = graft_forward (interval, start, end)) > 0)
1263 front_grafted = true;
1265 if (interval != null)
1266 interval = interval.Copy (mtext, start, end,
1269 || (next == null && end < interval.mtext.Length)));
1271 interval = new MInterval (Key, mtext, end - start, null);
1276 // .-this-. ==> .-this-.
1289 interval.Parent = i;
1290 for (; i != null; i = i.Parent)
1291 i.Length += interval.Length;
1294 Right.Insert (pos, interval, start, end);
1295 M17n.DebugPrint (" done\n");
1298 private void vacate_node (MInterval interval)
1300 vacate_node (interval, null);
1303 private void vacate_node (MInterval interval, MInterval stop)
1305 if (interval != null)
1306 M17n.DebugPrint ("vacate #{0} to #{1}\n", ID, interval.ID);
1308 M17n.DebugPrint ("vacate #{0} to null\n", ID);
1309 if (interval != null)
1310 interval.Parent = Parent;
1314 mtext.intervals.Put (Key, interval);
1318 if (this == Parent.Right)
1319 Parent.Right = interval;
1321 Parent.Left = interval;
1324 if (interval != null)
1325 diff -= interval.Length;
1326 for (MInterval i = Parent; i != stop; i = i.Parent)
1331 public void Delete (int start, int end)
1334 M17n.DebugPrint ("delete({0} {1}) from {2}\n", start, end, this);
1336 bool front_checked = false;
1337 bool rear_checked = false;
1343 if (end == From && isFrontSensitive)
1345 Left.Delete (start, end);
1348 if (isSensitive || isFrontSensitive)
1350 Left.Delete (start, From);
1352 end -= From - start;
1354 front_checked = true;
1360 if (start == To && isRearSensitive)
1362 Right.Delete (start, end);
1365 if (isSensitive || isRearSensitive)
1367 Right.Delete (To, end);
1369 rear_checked = true;
1375 Prev.Stack.Clear ();
1379 && isFrontSensitive)
1380 Next.Stack.Clear ();
1381 if (start == From && end == To)
1393 for (i = Right; i.Left != null; i = i.Left)
1394 i.Length += Left.Length;
1395 i.Length += Left.Length;
1399 vacate_node (Right);
1404 int len = end - start;
1407 || (From < start && isRearSensitive)
1408 || (end < To && isFrontSensitive))
1410 M17n.DebugPrint ("clear this stack\n");
1413 for (MInterval i = this; i != null; i = i.Parent)
1418 public void Push (int start, int end, MProperty prop)
1421 M17n.DebugPrint ("push({0} {1}) at {2}\n", start, end, this);
1426 Left.Push (start, end, prop);
1429 Left.Push (start, From, prop);
1436 Right.Push (start, end, prop);
1439 Right.Push (To, end, prop);
1443 if (! Stack.IsEmpty && isSensitive)
1446 divide_left (start);
1449 Stack.Push (prop.key, prop);
1452 /// Combine intervals between HEAD and TAIL (both inclusive) to
1453 /// the common parent of HEAD and TAIL. Callers should assure
1454 /// that the intervals are mergeable in advance.
1455 private static void combine (MInterval head, MInterval tail)
1457 M17n.DebugPrint ("combining {0} through {1}", head, tail);
1459 head.update_from_to ();
1460 tail.update_from_to ();
1461 int from = head.From;
1464 // The nearest common parent of HEAD and TAIL.
1466 for (root = head; root.To + root.RightLength < to;
1467 root = root.Parent);
1469 M17n.DebugPrint (" with common root {0}\n", root);
1471 if (from < root.From)
1473 MInterval prev = root.Prev;
1477 M17n.DebugPrint ("merging {0}\n", prev);
1478 prev.vacate_node (prev.Left, root);
1481 if (prev.Left != null)
1482 prev = prev.Left.RightMost;
1486 root.update_from_to ();
1490 MInterval next = root.Next;
1494 M17n.DebugPrint ("merging {0}\n", next);
1495 next.vacate_node (next.Right, root);
1498 if (next.Right != null)
1499 next = next.Right.LeftMost;
1503 root.update_from_to ();
1507 public void MergeAfterChange (int start, int end)
1511 MInterval head = find_head (start), i = head;
1512 MInterval tail = start < end ? find_tail (end) : head;
1514 if (tail.To < Length)
1517 if (start == head.From && start > 0)
1519 MInterval prev = head.Prev;
1520 if (head.mergeable (prev))
1523 M17n.DebugPrint ("merge between {0} and {1}\n", head, tail);
1526 MInterval next = i.Next;
1528 if (! i.mergeable (next))
1540 public void Pop (int start, int end)
1543 M17n.DebugPrint ("pop({0} {1}) at {2}\n", start, end, this);
1548 Left.Pop (start, end);
1551 Left.Pop (start, From);
1558 Right.Pop (start, end);
1561 Right.Pop (To, end);
1565 if (! Stack.IsEmpty)
1572 divide_left (start);
1580 public void PopSensitive (int start, int end)
1583 MInterval head = find_head (start);
1584 MInterval tail = find_tail (end);
1585 while (! head.Stack.IsEmpty && head.From > 0)
1587 MInterval prev = head.Prev;
1589 if (prev.Stack.IsEmpty || head.Stack.Val != prev.Stack.Val)
1593 while (! tail.Stack.IsEmpty && tail.To < mtext.Length)
1595 MInterval next = tail.Next;
1597 if (next.Stack.IsEmpty || tail.Stack.Val != next.Stack.Val)
1601 Pop (head.From, tail.To);
1604 public override string ToString ()
1606 string str = String.Format ("#{0}({1} {2} {3} [", ID, Length, From, To);
1608 foreach (MPlist p in Stack)
1612 str += ((MProperty) p.Val).Val;
1616 str += " " + ((MProperty) p.Val).Val;
1618 return (str + "])");
1621 private void DumpOne (bool with_prop, bool newline, bool force)
1623 if (force || M17n.debug)
1625 Console.Write ("#{0}({1} {2} {3}", ID, Length, From, To);
1626 if (with_prop && ! Stack.IsEmpty)
1628 string prepend = " [";
1629 foreach (MPlist p in Stack)
1631 Console.Write (prepend + ((MProperty) p.Val).Val);
1634 Console.Write ("]");
1636 Console.Write (")");
1638 Console.WriteLine ();
1640 throw new Exception ("Invalid interval length");
1644 public void Dump () { Dump (false); }
1646 public void Dump (bool force)
1648 if (force || M17n.debug)
1655 Console.Write (" ");
1656 DumpOne (true, false, force);
1663 get { return (Parent == null ? 0 : Parent.Depth + 1); }
1666 public void DumpNested (bool force)
1668 DumpNested (Key.ToString () + ":", force);
1671 public void DumpNested (string indent, bool force)
1673 if (force || M17n.debug)
1675 int indent_type = (Parent == null ? 1
1676 : Parent.Left == this ? 0 : 2);
1681 if (indent_type <= 1)
1682 Left.DumpNested (indent + " ", force);
1684 Left.DumpNested (indent + "| ", force);
1686 Console.Write (indent);
1687 if (indent_type == 0)
1688 Console.Write (".-");
1689 else if (indent_type == 2)
1690 Console.Write ("`-");
1691 DumpOne (true, true, true);
1694 if (indent_type >= 1)
1695 Right.DumpNested (indent + " ", force);
1697 Right.DumpNested (indent + "| ", force);
1703 private class MTextEnum : IEnumerator
1706 private int pos = -1;
1708 public MTextEnum (MText mt)
1713 public bool MoveNext ()
1716 return (pos < mt.nchars);
1719 public void Reset ()
1724 public object Current
1727 //if (pos < 0 || pos >= mt.nchars)
1728 //throw new InvalidOperationException ();