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
28 /// A text inserted before a character that has this property
29 /// inherits this property. If the text already has properties
30 /// of the same key, they are deleted. See the documentation of
31 /// Sensitive for exception.
33 /// A text inserted after a character that has this property
34 /// inherits this property. If the text already has properties
35 /// of the same key, they are deleted. See the documentation of
36 /// Sensitive for exception.
38 /// This property is deleted from a span of text if the span is
39 /// modified (i.e. a character is changed, a text is inserted,
40 /// some part is deleted). This propery is also deleted if a
41 /// property of the same key is added, which means that this
42 /// property is not stackable. If this property is also
43 /// FrontSticky (or RearSticky), text insertion just before (or
44 /// after) the span also deletes this property from the span of
52 public MSymbol Key { get { return key; } }
53 public object Val { get { return val; } }
55 public MProperty (MSymbol key, object val)
57 if (key.flags == null)
58 key.flags = Flags.None;
63 public MProperty (string name, object val)
65 key = MSymbol.PropertyKey (name);
69 public static bool HasFlags (MSymbol key, Flags flags)
71 return ((key.flags & flags) == flags);
74 public override string ToString ()
76 return key.ToString () + ":" + val;
80 public class MText : IEnumerable, IEquatable<MText>, IComparable<MText>
83 public enum MTextFormat format;
85 private StringBuilder sb;
87 private int cache_pos;
88 private int cache_idx;
89 private MPlist intervals;
90 private MPlist default_property;
91 private bool read_only;
93 private static UTF8Encoding utf8 = new UTF8Encoding ();
95 private static int count_chars (String str)
97 int len = str.Length, n = 0;
99 for (int i = 0; i < len; i++, n++)
100 if (surrogate_high_p (str[i]))
105 private static int count_chars (StringBuilder str)
107 int len = str.Length, n = 0;
109 for (int i = 0; i < len; i++, n++)
110 if (surrogate_high_p (str[i]))
117 sb = new StringBuilder ();
118 intervals = new MPlist ();
121 public MText (byte[] str)
123 sb = new StringBuilder (utf8.GetString (str));
124 nchars = count_chars (sb);
125 intervals = new MPlist ();
128 public MText (String str)
130 sb = new StringBuilder (str);
131 nchars = count_chars (str);
132 intervals = new MPlist ();
135 public MText (StringBuilder str)
138 nchars = count_chars (str);
139 intervals = new MPlist ();
142 public static MText operator+ (object obj, MText mt)
146 MText mtnew = new MText ((string) obj);
147 return mtnew.Ins (mtnew.Length, mt);
149 throw new Exception ("Unknown object type: " + obj.GetType());
152 public static MText operator+ (MText mt, object obj)
155 return mt + new MText ((string) obj);
157 return mt.Dup ().Ins (mt.Length, (int) obj);
159 return mt.Dup ().Ins (mt.Length, (int) ((char) obj));
160 throw new Exception ("Unknown object type: " + obj.GetType());
163 public static MText operator+ (MText mt1, MText mt2)
165 return mt1.Dup ().Ins (mt1.Length, mt2);
169 public bool ReadOnly { get { return read_only; } }
170 public int Length { get { return nchars; } }
174 // for IEnumerable interface
175 public IEnumerator GetEnumerator() { return new MTextEnum (this); }
177 // for IEquatable interface
178 public bool Equals (MText other) { return this.sb.Equals (other.sb); }
180 // for IComparable interface
181 public int CompareTo (MText other)
183 return this.sb.ToString ().CompareTo (other.sb.ToString ());
186 public override String ToString () { return "\"" + sb.ToString () + "\""; }
188 private static bool surrogate_high_p (char c)
190 return (c >= 0xD800 && c < 0xDC00);
193 private static bool surrogate_low_p (char c)
195 return (c >= 0xDC00 && c < 0xE000);
198 private static int inc_idx (StringBuilder sb, int i)
200 return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
203 private static int dec_idx (StringBuilder sb, int i)
205 return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
208 private static int pos_to_idx (MText mt, int pos)
210 if (pos == mt.cache_pos)
216 if (pos < mt.cache_pos)
218 if (mt.cache_pos == mt.cache_idx)
220 if (pos < mt.cache_pos - pos)
227 p = mt.cache_pos; i = mt.cache_idx;
233 if (mt.nchars - mt.cache_pos == mt.sb.Length - mt.cache_idx)
234 return (mt.cache_idx + pos - mt.cache_pos);
235 if (pos - mt.cache_pos < mt.nchars - pos)
237 p = mt.cache_pos; i = mt.cache_idx;
242 p = mt.nchars; i = mt.sb.Length;
247 for (; p < pos; i = inc_idx (mt.sb, i), p++);
249 for (; p > pos; i = dec_idx (mt.sb, i), p--);
255 private void check_pos (int pos, bool tail_ok)
257 if (pos < 0 || (tail_ok ? pos > nchars : pos >= nchars))
258 throw new Exception ("Invalid MText position:" + pos);
261 private bool check_range (int from, int to, bool zero_ok)
263 if (from < 0 || (zero_ok ? from > to : from >= to)
265 throw new Exception ("Invalid MText range");
269 private void insert (int pos, MText mt2, int from, int to)
271 check_pos (pos, true);
275 Console.Write ("inserting {0} to {1} of ", from, to);
276 mt2.DumpPropNested ();
280 foreach (MPlist plist in intervals)
282 MInterval root = (MInterval) plist.Val;
283 MPlist p = mt2.intervals.Find (plist.Key);
284 MInterval i = p == null ? null : (MInterval) p.Val;
286 root.Insert (pos, i, from, to);
288 foreach (MPlist plist in mt2.intervals)
289 if (intervals.Find (plist.Key) == null)
294 root = ((MInterval) plist.Val).Copy (this, from, to);
297 root = new MInterval (plist.Key, this);
298 root.Insert (pos, (MInterval) plist.Val, from, to);
300 intervals.Push (plist.Key, root);
303 int pos_idx = pos_to_idx (this, pos);
304 int from_idx = pos_to_idx (mt2, from);
305 int to_idx = pos_to_idx (mt2, to);
307 sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
311 private void insert (int pos, int c)
313 check_pos (pos, true);
315 int pos_idx = pos_to_idx (this, pos);
320 sb.Insert (pos_idx, ch);
324 char high = (char) (0xD800 + ((c - 0x10000) >> 10));
325 char low = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
326 sb.Insert (pos_idx, low);
327 sb.Insert (pos_idx, high);
330 foreach (MPlist plist in intervals)
331 ((MInterval) plist.Val).Insert (pos, null, 0, 1);
334 public int this[int i]
337 i = pos_to_idx (this, i);
340 if (surrogate_high_p (sb[i]))
342 sb[i] = (char) value;
346 char high = (char) (0xD800 + ((value - 0x10000) >> 10));
347 char low = (char) (0xDC00 + ((value - 0x10000) & 0x3FF));
349 if (! surrogate_high_p (sb[i]))
356 i = pos_to_idx (this, i);
357 return (surrogate_high_p (sb[i])
358 ? ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
365 MText mt = new MText (sb.ToString ());
367 foreach (MPlist p in intervals)
368 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, 0, Length));
372 public MText Dup (int from, int to)
374 if (check_range (from, to, true))
376 int from_idx = pos_to_idx (this, from);
377 int len = pos_to_idx (this, to) - from_idx;
378 MText mt = new MText (sb.ToString ().Substring (from_idx, len));
380 foreach (MPlist p in intervals)
381 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, from, to));
385 public MText Ins (int pos, int c)
391 public MText Ins (int pos, MText mt)
393 insert (pos, mt, 0, mt.nchars);
397 public MText Ins (int pos, MText mt, int from, int to)
399 insert (pos, mt, from, to);
403 public MText Cat (int c)
409 public MText Del (int from, int to)
411 if (check_range (from, to, true))
414 sb.Remove (from, pos_to_idx (this, to) - pos_to_idx (this, from));
418 foreach (MPlist plist in intervals)
420 MInterval root = (MInterval) plist.Val;
421 root.Delete (from, to);
422 if (from > 0 && from < nchars)
423 ((MInterval) plist.Val).MergeAfterChange (from, from);
432 public object GetProp (int pos, MSymbol key)
434 check_pos (pos, false);
436 MInterval i = (MInterval) intervals.Get (key);
440 MProperty prop = i.Get (pos);
441 return (prop != null ? prop.Val : null);
444 public object GetProp (int pos, MSymbol key, out MProperty prop)
446 check_pos (pos, false);
448 MInterval i = (MInterval) intervals.Get (key);
450 return (prop = null);
452 return (prop != null ? prop.Val : null);
455 public object GetProp (int pos, MSymbol key, out MProperty[] array)
457 check_pos (pos, false);
459 MInterval i = (MInterval) intervals.Get (key);
461 return (array = null);
462 MProperty prop = i.Get (pos, out array);
463 return (prop != null ? prop.Val : null);
466 public void PushProp (int from, int to, MSymbol key, object val)
468 if (! check_range (from, to, true))
469 PushProp (from, to, new MProperty (key, val));
472 public void PushProp (int from, int to, MProperty prop)
476 if (default_property == null)
477 default_property = new MPlist ();
478 default_property.Push (prop.key, prop.val);
482 if (check_range (from, to, true))
485 MPlist p = intervals.Find (prop.key);
490 root = new MInterval (prop.key, this);
491 intervals.Push (prop.key, root);
494 root = (MInterval) p.Val;
496 if (root.isSensitive)
497 root.PopSensitive (from, to);
498 root.Push (from, to, prop);
499 root.MergeAfterChange (from, to);
504 public void PopProp (int from, int to, MSymbol key)
508 if (default_property == null)
510 MPlist p = default_property.Find (key);
517 if (check_range (from, to, true))
520 MPlist p = intervals.Find (key);
524 MInterval root = (MInterval) p.Val;
525 if (root.isSensitive)
526 root.PopSensitive (from, to);
529 root = (MInterval) p.Val;
532 root.MergeAfterChange (from, to);
538 public void DumpProp ()
541 foreach (MPlist p in intervals)
542 ((MInterval) p.Val).Dump (true);
543 Console.WriteLine (")");
546 public void DumpPropNested ()
548 Console.WriteLine ("total length = {0}", Length);
549 foreach (MPlist p in intervals)
550 ((MInterval) p.Val).DumpNested (true);
553 private class MInterval
555 // position: 0 1 2 3 4 5 6 7
556 // | A | B | C | D | E F | G |
557 // interval |---|---|---|<->|-------|---|
558 // |---|<->|---| |<----->|---|
562 // [3 (1 2)] [3 (4 6)]
563 // [1 (0 1)] [2 (2 3)] [1 (6 7)]
565 private static int count = 0;
568 private int From, To;
570 private MPlist Stack;
571 private MInterval Left, Right, Parent;
574 public MInterval (MSymbol key, MText mt, int length)
577 throw new Exception ("Invalid interval length");
581 Stack = new MPlist ();
585 public MInterval (MSymbol key, MText mt)
589 Length = mt.sb.Length;
592 Stack = new MPlist ();
596 /// POS must be smaller than Length;
597 public MProperty Get (int pos)
599 MInterval i = find_head (pos);
601 return (i.Stack.IsEmpty ? null : (MProperty) i.Stack.Val);
604 /// POS must be smaller than Length;
605 public MProperty Get (int pos, out MProperty[] array)
607 MInterval i = find_head (pos);
616 array = new MProperty[i.Stack.Count];
620 for (idx = 0, p = i.Stack; ! p.IsEmpty; idx++, p = p.Next)
621 array[idx] = (MProperty) p.Val;
625 private MInterval (MSymbol key, MText mt, int length, MPlist stack)
632 Stack = stack == null ? new MPlist () : stack.Clone ();
636 private bool isRearSticky
638 get { return MProperty.HasFlags (Key, MProperty.Flags.RearSticky) ; }
641 private bool isFrontSticky
643 get { return MProperty.HasFlags (Key, MProperty.Flags.FrontSticky) ; }
646 public bool isSensitive
648 get { return MProperty.HasFlags (Key, MProperty.Flags.Sensitive) ; }
651 public bool isFrontSensitive
653 get { return MProperty.HasFlags (Key,
654 (MProperty.Flags.Sensitive
655 | MProperty.Flags.FrontSticky)); }
658 public bool isRearSensitive
660 get { return MProperty.HasFlags (Key,
661 (MProperty.Flags.Sensitive
662 | MProperty.Flags.RearSticky)); }
665 private void update_from_to ()
670 To = Length - RightLength;
672 else if (Parent.Left == this)
674 From = Parent.From - Length + LeftLength;
675 To = Parent.From - RightLength;
679 From = Parent.To + LeftLength;
680 To = Parent.To + Length - RightLength;
684 private int LeftLength
686 get { return (Left == null ? 0 : Left.Length); }
689 private int RightLength
691 get { return (Right == null ? 0 : Right.Length); }
694 private MInterval LeftMost
700 return Left.LeftMost;
704 private MInterval RightMost
710 return Right.RightMost;
714 private MInterval Prev {
720 for (i = Left; i.Right != null; i = i.Right)
726 MInterval child = this;
727 for (i = Parent; i != null && i.Left == child;
728 child = i, i = i.Parent);
734 private MInterval Next {
740 for (i = Right; i.Left != null; i = i.Left)
746 MInterval child = this;
747 for (i = Parent; i != null && i.Right == child;
748 child = i, i = i.Parent);
754 private MInterval find_head (int pos)
758 return Left.find_head (pos);
760 return Right.find_head (pos);
764 private MInterval find_tail (int pos)
768 return Left.find_tail (pos);
770 return Right.find_tail (pos);
774 private bool mergeable (MInterval i)
778 for (p1 = Stack, p2 = i.Stack; ! p1.IsEmpty && ! p2.IsEmpty;
779 p1 = p1.Next, p2 = p2.Next)
780 if (p1.Val != p2.Val)
782 return (p1.IsEmpty && p2.IsEmpty);
785 // p-. or .-p p-. or .-p
786 // .-this-. .-right-.
787 // left .-right-. -> .-this-. c2
789 private MInterval promote_right ()
791 MInterval c1 = Right.Left;
795 mtext.intervals.Put (Key, Right);
796 else if (Parent.Left == this)
799 Parent.Right = Right;
802 Right.Parent = Parent;
804 Right.Length += LeftLength + (To - From);
809 Length = LeftLength + (To - From) + RightLength;
811 // Update C1 if necessary.
815 Parent.update_from_to ();
819 // p-. or .-p p-. or .-p
821 // .-left-. .-right-. -> c1 .-this-.
823 private MInterval promote_left ()
825 MInterval c2 = Left.Right;
829 mtext.intervals.Put (Key, Left);
830 else if (Parent.Left == this)
836 Left.Parent = Parent;
838 Left.Length += (To - From) + RightLength;
843 Length = LeftLength + (To - From) + RightLength;
845 // Update C2 if necessary.
849 Parent.update_from_to ();
853 public MInterval Balance ()
861 // .-left-. .-right-.
863 int diff = i.LeftLength - i.RightLength;
868 new_diff = (i.Length - i.LeftLength
869 + i.Left.RightLength - i.Left.LeftLength);
870 if (Math.Abs (new_diff) >= diff)
872 M17n.DebugPrint ("balancing #{0} by promoting left...", i.ID);
873 i = i.promote_left ();
874 M17n.DebugPrint ("done\n");
879 new_diff = (i.Length - i.RightLength
880 + i.Right.LeftLength - i.Right.RightLength);
881 if (Math.Abs (new_diff) >= diff)
883 M17n.DebugPrint ("balancing #{0} by promoting right\n", i.ID);
884 i = i.promote_right ();
893 public MInterval Copy (MText mt, int start, int end)
895 MInterval copy, left_copy = null, right_copy = null;
902 return Left.Copy (mt, start, end);
903 left_copy = Left.Copy (mt, start, From);
908 return Right.Copy (mt, start, end);
909 right_copy = Right.Copy (mt, To, end);
912 copy = new MInterval (Key, null, end - start, Stack);
914 if (isSensitive && (From < start || end < To))
916 if (left_copy != null)
918 copy.Left = left_copy;
919 left_copy.Parent = copy;
921 if (right_copy != null)
923 copy.Right = right_copy;
924 right_copy.Parent = copy;
932 private MInterval divide_right (int pos)
934 MInterval interval = new MInterval (Key, mtext, To - pos, Stack);
936 M17n.DebugPrint ("divide-right({0}) at ", pos); DumpOne (false, true);
940 interval.Right = Right;
941 Right.Parent = interval;
942 interval.Length += Right.Length;
944 interval.Parent = this;
952 private MInterval divide_left (int pos)
954 MInterval interval = new MInterval (Key, mtext, pos - From, Stack);
956 M17n.DebugPrint ("divide-left({0}) at ", pos); DumpOne (false, true);
960 interval.Left = Left;
961 Left.Parent = interval;
962 interval.Length += Left.Length;
964 interval.Parent = this;
969 private void set_mtext (MText mt)
975 Right.set_mtext (mt);
978 private void enlarge (int len)
982 for (MInterval prev = this, i = this.Parent; i != null;
983 prev = i, i = i.Parent)
994 private int graft_forward (MInterval interval, int start, int end)
998 if (! Stack.IsEmpty && isRearSticky)
1000 else if (interval == null)
1001 len = Stack.IsEmpty ? end - start : 0;
1004 MInterval i = interval.find_head (start);
1007 while (i != null && mergeable (i))
1009 M17n.DebugPrint (" grafting "); i.DumpOne (false, false);
1010 len += i.To - i.From;
1012 len -= start - i.From;
1022 M17n.DebugPrint (" grafted {0} in ", len); DumpOne (false, true);
1028 private int graft_backward (MInterval interval, int start, int end)
1032 if (! Stack.IsEmpty && isFrontSticky)
1034 else if (interval == null)
1035 len = Stack.IsEmpty ? end - start : 0;
1038 MInterval i = interval.find_tail (end);
1041 while (i != null && mergeable (i))
1043 M17n.DebugPrint (" grafting "); i.DumpOne (false, false);
1044 len += i.To - i.From;
1047 if (i.From <= start)
1049 len -= start - i.From;
1056 M17n.DebugPrint (" grafted {0} in ", len); DumpOne (false, true);
1062 public void Insert (int pos, MInterval interval, int start, int end)
1066 M17n.DebugPrint ("insert({0} to {1}) at {2} in ", start, end, pos);
1067 DumpOne (false, false);
1070 Left.Insert (pos, interval, start, end);
1071 else if (pos == From)
1073 MInterval prev = Left != null ? Prev : null;
1075 if (isFrontSensitive)
1077 if (prev != null && isRearSensitive)
1078 prev.Stack.Clear ();
1079 if (prev != null && isRearSticky && ! prev.Stack.IsEmpty)
1081 prev.enlarge (end - start);
1084 if (isFrontSticky && ! Stack.IsEmpty)
1086 enlarge (end - start);
1091 start += prev.graft_forward (interval, start, end);
1095 if ((end -= graft_backward (interval, start, end)) == start)
1098 if (interval != null)
1099 interval = interval.Copy (mtext, start, end);
1101 interval = new MInterval (Key, mtext, end - start, null);
1106 // .-this-. ==> .-this-.
1118 interval.Parent = i;
1119 for (; i != null; i = i.Parent)
1120 i.Length += interval.Length;
1126 else if (! Stack.IsEmpty && (isFrontSticky || isRearSticky))
1128 enlarge (end - start);
1131 int len = graft_forward (interval, start, end);
1135 if ((end -= graft_backward (interval, start, end)) == start)
1138 if (interval != null)
1139 interval = interval.Copy (mtext, start, end);
1141 interval = new MInterval (Key, mtext, end - start, null);
1144 Right.Left = interval;
1145 interval.Parent = Right;
1146 for (MInterval i = Right; i != null; i = i.Parent)
1147 i.Length += interval.Length;
1151 MInterval next = Right != null ? Next : null;
1153 if (isRearSensitive)
1155 if (next != null && isFrontSensitive)
1156 next.Stack.Clear ();
1157 if (isRearSticky && ! Stack.IsEmpty)
1159 enlarge (end - start);
1164 if (isFrontSticky && ! next.Stack.IsEmpty)
1166 next.enlarge (end - start);
1169 end -= next.graft_backward (interval, start, end);
1174 if ((start += graft_forward (interval, start, end)) == end)
1177 if (interval != null)
1178 interval = interval.Copy (mtext, start, end);
1180 interval = new MInterval (Key, mtext, end - start, null);
1185 // .-this-. ==> .-this-.
1198 interval.Parent = i;
1199 for (; i != null; i = i.Parent)
1200 i.Length += interval.Length;
1203 Right.Insert (pos, interval, start, end);
1204 M17n.DebugPrint (" done\n");
1207 private void vacate_node (MInterval interval)
1209 vacate_node (interval, null);
1212 private void vacate_node (MInterval interval, MInterval stop)
1214 if (interval != null)
1215 M17n.DebugPrint ("vacate #{0} to #{1}\n", ID, interval.ID);
1217 M17n.DebugPrint ("vacate #{0} to null\n", ID);
1218 if (interval != null)
1219 interval.Parent = Parent;
1223 mtext.intervals.Put (Key, interval);
1227 if (this == Parent.Right)
1228 Parent.Right = interval;
1230 Parent.Left = interval;
1233 if (interval != null)
1234 diff -= interval.Length;
1235 for (MInterval i = Parent; i != stop; i = i.Parent)
1240 public void Delete (int start, int end)
1243 M17n.DebugPrint ("delete({0} {1}) from ", start, end); DumpOne (false, true);
1248 Left.Delete (start, end);
1251 Left.Delete (start, From);
1253 end -= From - start;
1260 Right.Delete (start, end);
1263 Right.Delete (To, end);
1266 if (start == From && end == To)
1278 for (i = Right; i.Left != null; i = i.Left)
1279 i.Length += Left.Length;
1280 i.Length += Left.Length;
1284 vacate_node (Right);
1289 int len = end - start;
1291 for (MInterval i = this; i != null; i = i.Parent)
1296 public void Push (int start, int end, MProperty prop)
1299 M17n.DebugPrint ("push({0} {1}) at ", start, end); DumpOne (false, true);
1304 Left.Push (start, end, prop);
1307 Left.Push (start, From, prop);
1314 Right.Push (start, end, prop);
1317 Right.Push (To, end, prop);
1322 divide_left (start);
1325 Stack.Push (prop.key, prop);
1328 /// Combine intervals between HEAD and TAIL (both inclusive) to
1329 /// the common parent of HEAD and TAIL while assuming that the
1330 /// intervals are mergeable.
1331 private static void combine (MInterval head, MInterval tail)
1333 M17n.DebugPrint ("combining "); head.DumpOne (true, false);
1334 M17n.DebugPrint (" through "); tail.DumpOne (true, false);
1336 int from = head.From;
1338 // The nearest common parent of HEAD and TAIL.
1340 for (root = head; root.To + root.RightLength < to;
1341 root = root.Parent);
1343 M17n.DebugPrint (" common root is "); root.DumpOne (false, true);
1345 if (from < root.From)
1347 MInterval prev = root.Prev;
1351 M17n.DebugPrint ("merging "); prev.DumpOne (false, true);
1352 prev.vacate_node (prev.Left, root);
1355 if (prev.Left != null)
1356 prev = prev.Left.RightMost;
1360 root.update_from_to ();
1364 MInterval next = root.Next;
1368 M17n.DebugPrint ("merging "); next.DumpOne (false, true);
1369 next.vacate_node (next.Right, root);
1372 if (next.Right != null)
1373 next = next.Right.LeftMost;
1377 root.update_from_to ();
1381 private void check_from_to (string str)
1383 int save_from = From;
1386 if (save_from != From || save_to != To)
1387 throw new Exception (str + ":incorrect from or to");
1390 public void MergeAfterChange (int start, int end)
1394 MInterval head = find_head (start), i = head;
1395 MInterval tail = find_tail (end).Next;
1397 if (start == head.From && start > 0)
1400 if (! head.mergeable (i))
1405 MInterval next = i.Next;
1407 if (next == null || ! i.mergeable (next))
1417 public void Pop (int start, int end)
1420 M17n.DebugPrint ("pop({0} {1}) at ", start, end); DumpOne (false, true);
1425 Left.Pop (start, end);
1428 Left.Pop (start, From);
1435 Right.Pop (start, end);
1438 Right.Pop (To, end);
1442 if (! Stack.IsEmpty)
1445 divide_left (start);
1452 public void PopSensitive (int start, int end)
1455 MInterval head = find_head (start);
1456 MInterval tail = find_tail (end);
1457 while (! head.Stack.IsEmpty && head.From > 0)
1459 MInterval prev = head.Prev;
1461 if (prev.Stack.IsEmpty || head.Stack.Val != prev.Stack.Val)
1465 while (! tail.Stack.IsEmpty && tail.To < mtext.Length)
1467 MInterval next = tail.Next;
1469 if (next.Stack.IsEmpty || tail.Stack.Val != next.Stack.Val)
1473 Pop (head.From, tail.To);
1476 private void DumpOne (bool with_prop, bool newline)
1478 DumpOne (with_prop, newline, false);
1481 private void DumpOne (bool with_prop, bool newline, bool force)
1483 if (force || M17n.debug)
1485 Console.Write ("#{0}({1} {2} {3}", ID, Length, From, To);
1486 if (with_prop && ! Stack.IsEmpty)
1488 string prepend = " [";
1489 foreach (MPlist p in Stack)
1491 Console.Write (prepend + ((MProperty) p.Val).Val);
1494 Console.Write ("]");
1496 Console.Write (")");
1498 Console.WriteLine ();
1500 throw new Exception ("Invalid interval length");
1504 public void Dump () { Dump (false); }
1506 public void Dump (bool force)
1508 if (force || M17n.debug)
1515 Console.Write (" ");
1516 DumpOne (true, false, force);
1523 get { return (Parent == null ? 0 : Parent.Depth + 1); }
1526 public void DumpNested (bool force)
1528 DumpNested (Key.ToString () + ":", force);
1531 public void DumpNested (string indent, bool force)
1533 if (force || M17n.debug)
1535 int indent_type = (Parent == null ? 1
1536 : Parent.Left == this ? 0 : 2);
1541 if (indent_type <= 1)
1542 Left.DumpNested (indent + " ", force);
1544 Left.DumpNested (indent + "| ", force);
1546 Console.Write (indent);
1547 if (indent_type == 0)
1548 Console.Write (".-");
1549 else if (indent_type == 2)
1550 Console.Write ("`-");
1551 DumpOne (true, true, true);
1554 if (indent_type >= 1)
1555 Right.DumpNested (indent + " ", force);
1557 Right.DumpNested (indent + "| ", force);
1563 private class MTextEnum : IEnumerator
1566 private int pos = -1;
1568 public MTextEnum (MText mt)
1573 public bool MoveNext ()
1576 return (pos < mt.nchars);
1579 public void Reset ()
1584 public object Current
1587 //if (pos < 0 || pos >= mt.nchars)
1588 //throw new InvalidOperationException ();