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 = MProperty.Flags.None;
63 public MProperty (string name, object val)
65 key = MSymbol.PropertyKey (name);
69 public override string ToString ()
71 return key.ToString () + ":" + val;
75 public class MText : IEnumerable, IEquatable<MText>, IComparable<MText>
78 public enum MTextFormat format;
80 private StringBuilder sb;
82 private int cache_pos;
83 private int cache_idx;
84 private MPlist intervals;
85 private MPlist default_property;
86 private bool read_only;
88 private static UTF8Encoding utf8 = new UTF8Encoding ();
90 private static int count_chars (String str)
92 int len = str.Length, n = 0;
94 for (int i = 0; i < len; i++, n++)
95 if (surrogate_high_p (str[i]))
100 private static int count_chars (StringBuilder str)
102 int len = str.Length, n = 0;
104 for (int i = 0; i < len; i++, n++)
105 if (surrogate_high_p (str[i]))
112 sb = new StringBuilder ();
113 intervals = new MPlist ();
116 public MText (byte[] str)
118 sb = new StringBuilder (utf8.GetString (str));
119 nchars = count_chars (sb);
120 intervals = new MPlist ();
123 public MText (String str)
125 sb = new StringBuilder (str);
126 nchars = count_chars (str);
127 intervals = new MPlist ();
130 public MText (StringBuilder str)
133 nchars = count_chars (str);
134 intervals = new MPlist ();
137 public static MText operator+ (object obj, MText mt)
140 return new MText ((string) obj) + mt;
141 throw new Exception ("Unknown object type: " + obj.GetType());
144 public static MText operator+ (MText mt1, MText mt2)
146 MText mt = new MText ();
148 mt.sb.Append (mt1.sb);
149 mt.sb.Append (mt2.sb);
150 mt.nchars = mt1.nchars + mt2.nchars;
154 public static MText operator+ (string str, MText mt)
156 MText mtnew = new MText (str);
158 mtnew.sb.Append (mt.sb);
159 mtnew.nchars += mt.nchars;
164 public bool ReadOnly { get { return read_only; } }
165 public int Length { get { return nchars; } }
169 // for IEnumerable interface
170 public IEnumerator GetEnumerator() { return new MTextEnum (this); }
172 // for IEquatable interface
173 public bool Equals (MText other) { return this.sb.Equals (other.sb); }
175 // for IComparable interface
176 public int CompareTo (MText other)
178 return this.sb.ToString ().CompareTo (other.sb.ToString ());
181 public override String ToString () { return "\"" + sb.ToString () + "\""; }
183 private static bool surrogate_high_p (char c)
185 return (c >= 0xD800 && c < 0xDC00);
188 private static bool surrogate_low_p (char c)
190 return (c >= 0xDC00 && c < 0xE000);
193 private static int inc_idx (StringBuilder sb, int i)
195 return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
198 private static int dec_idx (StringBuilder sb, int i)
200 return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
203 private static int pos_to_idx (MText mt, int pos)
205 if (pos == mt.cache_pos)
211 if (pos < mt.cache_pos)
213 if (mt.cache_pos == mt.cache_idx)
215 if (pos < mt.cache_pos - pos)
222 p = mt.cache_pos; i = mt.cache_idx;
228 if (mt.nchars - mt.cache_pos == mt.sb.Length - mt.cache_idx)
229 return (mt.cache_idx + pos - mt.cache_pos);
230 if (pos - mt.cache_pos < mt.nchars - pos)
232 p = mt.cache_pos; i = mt.cache_idx;
237 p = mt.nchars; i = mt.sb.Length;
242 for (; p < pos; i = inc_idx (mt.sb, i), p++);
244 for (; p > pos; i = dec_idx (mt.sb, i), p--);
250 private void check_pos (int pos, bool tail_ok)
252 if (pos < 0 || (tail_ok ? pos > nchars : pos >= nchars))
253 throw new Exception ("Invalid MText position:" + pos);
256 private bool check_range (int from, int to, bool zero_ok)
258 if (from < 0 || (zero_ok ? from > to : from >= to)
260 throw new Exception ("Invalid MText range");
264 private void insert (int pos, MText mt2, int from, int to)
266 check_pos (pos, true);
270 Console.Write ("inserting {0} to {1} of ", from, to);
271 mt2.DumpPropNested ();
275 foreach (MPlist plist in intervals)
277 MInterval root = (MInterval) plist.Val;
278 MPlist p = mt2.intervals.Find (plist.Key);
279 MInterval i = p == null ? null : (MInterval) p.Val;
281 root.Insert (pos, i, from, to);
283 foreach (MPlist plist in mt2.intervals)
284 if (intervals.Find (plist.Key) == null)
289 root = ((MInterval) plist.Val).Copy (this, from, to);
292 root = new MInterval (plist.Key, this);
293 root.Insert (pos, (MInterval) plist.Val, from, to);
295 intervals.Push (plist.Key, root);
298 int pos_idx = pos_to_idx (this, pos);
299 int from_idx = pos_to_idx (mt2, from);
300 int to_idx = pos_to_idx (mt2, to);
302 sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
306 private void insert (int pos, int c)
308 check_pos (pos, true);
310 int pos_idx = pos_to_idx (this, pos);
315 sb.Insert (pos_idx, ch);
319 char high = (char) (0xD800 + ((c - 0x10000) >> 10));
320 char low = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
321 sb.Insert (pos_idx, low);
322 sb.Insert (pos_idx, high);
325 foreach (MPlist plist in intervals)
326 ((MInterval) plist.Val).Insert (pos, null, 0, 1);
329 public int this[int i]
332 i = pos_to_idx (this, i);
335 if (surrogate_high_p (sb[i]))
337 sb[i] = (char) value;
341 char high = (char) (0xD800 + ((value - 0x10000) >> 10));
342 char low = (char) (0xDC00 + ((value - 0x10000) & 0x3FF));
344 if (! surrogate_high_p (sb[i]))
351 i = pos_to_idx (this, i);
352 return (surrogate_high_p (sb[i])
353 ? ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
360 MText mt = new MText (sb.ToString ());
362 foreach (MPlist p in intervals)
363 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, 0, Length));
367 public MText Dup (int from, int to)
369 if (check_range (from, to, true))
371 int from_idx = pos_to_idx (this, from);
372 int len = pos_to_idx (this, to) - from_idx;
373 MText mt = new MText (sb.ToString ().Substring (from_idx, len));
375 foreach (MPlist p in intervals)
376 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, from, to));
380 public MText Ins (int pos, int c)
386 public MText Ins (int pos, MText mt)
388 insert (pos, mt, 0, mt.nchars);
392 public MText Ins (int pos, MText mt, int from, int to)
394 insert (pos, mt, from, to);
398 public MText Cat (int c)
404 public MText Del (int from, int to)
406 if (check_range (from, to, true))
409 sb.Remove (from, pos_to_idx (this, to) - pos_to_idx (this, from));
413 foreach (MPlist plist in intervals)
415 MInterval root = (MInterval) plist.Val;
416 root.Delete (from, to);
417 if (from > 0 && from < nchars)
418 ((MInterval) plist.Val).MergeAfterChange (from, from);
427 public object GetProp (int pos, MSymbol key)
429 check_pos (pos, false);
431 MInterval i = (MInterval) intervals.Get (key);
435 MProperty prop = i.Get (pos);
436 return (prop != null ? prop.Val : null);
439 public object GetProp (int pos, MSymbol key, out MProperty prop)
441 check_pos (pos, false);
443 MInterval i = (MInterval) intervals.Get (key);
445 return (prop = null);
447 return (prop != null ? prop.Val : null);
450 public object GetProp (int pos, MSymbol key, out MProperty[] array)
452 check_pos (pos, false);
454 MInterval i = (MInterval) intervals.Get (key);
456 return (array = null);
457 MProperty prop = i.Get (pos, out array);
458 return (prop != null ? prop.Val : null);
461 public void PushProp (int from, int to, MSymbol key, object val)
463 if (! check_range (from, to, true))
464 PushProp (from, to, new MProperty (key, val));
467 public void PushProp (int from, int to, MProperty prop)
471 if (default_property == null)
472 default_property = new MPlist ();
473 default_property.Push (prop.key, prop.val);
477 if (check_range (from, to, true))
480 MPlist p = intervals.Find (prop.key);
485 root = new MInterval (prop.key, this);
486 intervals.Push (prop.key, root);
489 root = (MInterval) p.Val;
491 if (root.isSensitive)
492 root.PopSensitive (from, to);
493 root.Push (from, to, prop);
494 root.MergeAfterChange (from, to);
499 public void PopProp (int from, int to, MSymbol key)
503 if (default_property == null)
505 MPlist p = default_property.Find (key);
512 if (check_range (from, to, true))
515 MPlist p = intervals.Find (key);
519 MInterval root = (MInterval) p.Val;
520 if (root.isSensitive)
521 root.PopSensitive (from, to);
524 root = (MInterval) p.Val;
527 root.MergeAfterChange (from, to);
533 public void DumpProp ()
536 foreach (MPlist p in intervals)
537 ((MInterval) p.Val).Dump (true);
538 Console.WriteLine (")");
541 public void DumpPropNested ()
543 Console.WriteLine ("total length = {0}", Length);
544 foreach (MPlist p in intervals)
545 ((MInterval) p.Val).DumpNested (true);
548 private class MInterval
550 // position: 0 1 2 3 4 5 6 7
551 // | A | B | C | D | E F | G |
552 // interval |---|---|---|<->|-------|---|
553 // |---|<->|---| |<----->|---|
557 // [3 (1 2)] [3 (4 6)]
558 // [1 (0 1)] [2 (2 3)] [1 (6 7)]
560 private static int count = 0;
563 private int From, To;
565 private MPlist Stack;
566 private MInterval Left, Right, Parent;
569 public MInterval (MSymbol key, MText mt, int length)
572 throw new Exception ("Invalid interval length");
576 Stack = new MPlist ();
580 public MInterval (MSymbol key, MText mt)
584 Length = mt.sb.Length;
587 Stack = new MPlist ();
591 /// POS must be smaller than Length;
592 public MProperty Get (int pos)
594 MInterval i = find_head (pos);
596 return (i.Stack.IsEmpty ? null : (MProperty) i.Stack.Val);
599 /// POS must be smaller than Length;
600 public MProperty Get (int pos, out MProperty[] array)
602 MInterval i = find_head (pos);
611 array = new MProperty[i.Stack.Count];
615 for (idx = 0, p = i.Stack; ! p.IsEmpty; idx++, p = p.Next)
616 array[idx] = (MProperty) p.Val;
620 private MInterval (MSymbol key, MText mt, int length, MPlist stack)
627 Stack = stack == null ? new MPlist () : stack.Clone ();
631 private bool isRearSticky
633 get { return ((Key.flags & MProperty.Flags.RearSticky)
634 != MProperty.Flags.None); }
637 private bool isFrontSticky
639 get { return ((Key.flags & MProperty.Flags.FrontSticky)
640 != MProperty.Flags.None); }
643 public bool isSensitive
645 get { return ((Key.flags & MProperty.Flags.Sensitive)
646 != MProperty.Flags.None); }
649 private void update_from_to ()
654 To = Length - RightLength;
656 else if (Parent.Left == this)
658 From = Parent.From - Length + LeftLength;
659 To = Parent.From - RightLength;
663 From = Parent.To + LeftLength;
664 To = Parent.To + Length - RightLength;
668 private int LeftLength
670 get { return (Left == null ? 0 : Left.Length); }
673 private int RightLength
675 get { return (Right == null ? 0 : Right.Length); }
678 private MInterval LeftMost
684 return Left.LeftMost;
688 private MInterval RightMost
694 return Right.RightMost;
698 private MInterval Prev {
704 for (i = Left; i.Right != null; i = i.Right)
710 MInterval child = this;
711 for (i = Parent; i != null && i.Left == child;
712 child = i, i = i.Parent);
718 private MInterval Next {
724 for (i = Right; i.Left != null; i = i.Left)
730 MInterval child = this;
731 for (i = Parent; i != null && i.Right == child;
732 child = i, i = i.Parent);
738 private MInterval find_head (int pos)
742 return Left.find_head (pos);
744 return Right.find_head (pos);
748 private MInterval find_tail (int pos)
752 return Left.find_tail (pos);
754 return Right.find_tail (pos);
758 private bool mergeable (MInterval i)
762 for (p1 = Stack, p2 = i.Stack; ! p1.IsEmpty && ! p2.IsEmpty;
763 p1 = p1.Next, p2 = p2.Next)
764 if (p1.Val != p2.Val)
766 return (p1.IsEmpty && p2.IsEmpty);
769 // p-. or .-p p-. or .-p
770 // .-this-. .-right-.
771 // left .-right-. -> .-this-. c2
773 private MInterval promote_right ()
775 MInterval c1 = Right.Left;
779 mtext.intervals.Put (Key, Right);
780 else if (Parent.Left == this)
783 Parent.Right = Right;
786 Right.Parent = Parent;
788 Right.Length += LeftLength + (To - From);
793 Length = LeftLength + (To - From) + RightLength;
795 // Update C1 if necessary.
799 Parent.update_from_to ();
803 // p-. or .-p p-. or .-p
805 // .-left-. .-right-. -> c1 .-this-.
807 private MInterval promote_left ()
809 MInterval c2 = Left.Right;
813 mtext.intervals.Put (Key, Left);
814 else if (Parent.Left == this)
820 Left.Parent = Parent;
822 Left.Length += (To - From) + RightLength;
827 Length = LeftLength + (To - From) + RightLength;
829 // Update C2 if necessary.
833 Parent.update_from_to ();
837 public MInterval Balance ()
845 // .-left-. .-right-.
847 int diff = i.LeftLength - i.RightLength;
852 new_diff = (i.Length - i.LeftLength
853 + i.Left.RightLength - i.Left.LeftLength);
854 if (Math.Abs (new_diff) >= diff)
856 M17n.DebugPrint ("balancing #{0} by promoting left...", i.ID);
857 i = i.promote_left ();
858 M17n.DebugPrint ("done\n");
863 new_diff = (i.Length - i.RightLength
864 + i.Right.LeftLength - i.Right.RightLength);
865 if (Math.Abs (new_diff) >= diff)
867 M17n.DebugPrint ("balancing #{0} by promoting right\n", i.ID);
868 i = i.promote_right ();
877 public MInterval Copy (MText mt, int start, int end)
879 MInterval copy, left_copy = null, right_copy = null;
886 return Left.Copy (mt, start, end);
887 left_copy = Left.Copy (mt, start, From);
892 return Right.Copy (mt, start, end);
893 right_copy = Right.Copy (mt, To, end);
896 copy = new MInterval (Key, null, end - start, Stack);
898 if (isSensitive && (From < start || end < To))
900 if (left_copy != null)
902 copy.Left = left_copy;
903 left_copy.Parent = copy;
905 if (right_copy != null)
907 copy.Right = right_copy;
908 right_copy.Parent = copy;
916 private MInterval divide_right (int pos)
918 MInterval interval = new MInterval (Key, mtext, To - pos, Stack);
920 M17n.DebugPrint ("divide-right({0}) at ", pos); DumpOne (false, true);
924 interval.Right = Right;
925 Right.Parent = interval;
926 interval.Length += Right.Length;
928 interval.Parent = this;
936 private MInterval divide_left (int pos)
938 MInterval interval = new MInterval (Key, mtext, pos - From, Stack);
940 M17n.DebugPrint ("divide-left({0}) at ", pos); DumpOne (false, true);
944 interval.Left = Left;
945 Left.Parent = interval;
946 interval.Length += Left.Length;
948 interval.Parent = this;
953 private void set_mtext (MText mt)
959 Right.set_mtext (mt);
962 private void enlarge (int len)
966 for (MInterval prev = this, i = this.Parent; i != null;
967 prev = i, i = i.Parent)
978 private int graft_forward (MInterval interval, int start, int end)
982 if (! Stack.IsEmpty && isRearSticky)
984 else if (interval == null)
985 len = Stack.IsEmpty ? end - start : 0;
988 MInterval i = interval.find_head (start);
991 while (i != null && mergeable (i))
993 M17n.DebugPrint (" grafting "); i.DumpOne (false, false);
994 len += i.To - i.From;
996 len -= start - i.From;
1006 M17n.DebugPrint (" grafted {0} in ", len); DumpOne (false, true);
1012 private int graft_backward (MInterval interval, int start, int end)
1016 if (! Stack.IsEmpty && isFrontSticky)
1018 else if (interval == null)
1019 len = Stack.IsEmpty ? end - start : 0;
1022 MInterval i = interval.find_tail (end);
1025 while (i != null && mergeable (i))
1027 M17n.DebugPrint (" grafting "); i.DumpOne (false, false);
1028 len += i.To - i.From;
1031 if (i.From <= start)
1033 len -= start - i.From;
1040 M17n.DebugPrint (" grafted {0} in ", len); DumpOne (false, true);
1046 public void Insert (int pos, MInterval interval, int start, int end)
1050 M17n.DebugPrint ("insert({0} to {1}) at {2} in ", start, end, pos);
1051 DumpOne (false, false);
1054 Left.Insert (pos, interval, start, end);
1055 else if (pos == From)
1059 MInterval prev = Prev;
1061 if (prev.isSensitive && prev.isRearSticky)
1062 prev.Stack.Clear ();
1063 start += prev.graft_forward (interval, start, end);
1065 if (isSensitive && isFrontSticky)
1069 end -= graft_backward (interval, start, end);
1072 if (interval != null)
1073 interval = interval.Copy (mtext, start, end);
1075 interval = new MInterval (Key, mtext, end - start, null);
1080 // .-this-. ==> .-this-.
1092 interval.Parent = i;
1093 for (; i != null; i = i.Parent)
1094 i.Length += interval.Length;
1103 int len = graft_forward (interval, start, end);
1108 end -= graft_backward (interval, start, end);
1111 if (interval != null)
1112 interval = interval.Copy (mtext, start, end);
1114 interval = new MInterval (Key, mtext, end - start, null);
1117 Right.Left = interval;
1118 interval.Parent = Right;
1119 for (MInterval i = Right; i != null; i = i.Parent)
1120 i.Length += interval.Length;
1128 MInterval next = Next;
1130 if (next.isSensitive && next.isFrontSticky)
1131 next.Stack.Clear ();
1132 end -= next.graft_backward (interval, start, end);
1134 if (isSensitive && isRearSticky)
1138 start += graft_forward (interval, start, end);
1141 if (interval != null)
1142 interval = interval.Copy (mtext, start, end);
1144 interval = new MInterval (Key, mtext, end - start, null);
1149 // .-this-. ==> .-this-.
1162 interval.Parent = i;
1163 for (; i != null; i = i.Parent)
1164 i.Length += interval.Length;
1169 Next.Insert (pos, interval, start, end);
1170 M17n.DebugPrint (" done\n");
1173 private void vacate_node (MInterval interval)
1175 vacate_node (interval, null);
1178 private void vacate_node (MInterval interval, MInterval stop)
1180 if (interval != null)
1181 M17n.DebugPrint ("vacate #{0} to #{1}\n", ID, interval.ID);
1183 M17n.DebugPrint ("vacate #{0} to null\n", ID);
1184 if (interval != null)
1185 interval.Parent = Parent;
1189 mtext.intervals.Put (Key, interval);
1193 if (this == Parent.Right)
1194 Parent.Right = interval;
1196 Parent.Left = interval;
1199 if (interval != null)
1200 diff -= interval.Length;
1201 for (MInterval i = Parent; i != stop; i = i.Parent)
1206 public void Delete (int start, int end)
1209 M17n.DebugPrint ("delete({0} {1}) from ", start, end); DumpOne (false, true);
1214 Left.Delete (start, end);
1217 Left.Delete (start, From);
1219 end -= From - start;
1226 Right.Delete (start, end);
1229 Right.Delete (To, end);
1232 if (start == From && end == To)
1244 for (i = Right; i.Left != null; i = i.Left)
1245 i.Length += Left.Length;
1246 i.Length += Left.Length;
1250 vacate_node (Right);
1255 int len = end - start;
1257 for (MInterval i = this; i != null; i = i.Parent)
1262 public void Push (int start, int end, MProperty prop)
1265 M17n.DebugPrint ("push({0} {1}) at ", start, end); DumpOne (false, true);
1270 Left.Push (start, end, prop);
1273 Left.Push (start, From, prop);
1280 Right.Push (start, end, prop);
1283 Right.Push (To, end, prop);
1288 divide_left (start);
1291 Stack.Push (prop.key, prop);
1294 /// Combine intervals between HEAD and TAIL (both inclusive) to
1295 /// the common parent of HEAD and TAIL while assuming that the
1296 /// intervals are mergeable.
1297 private static void combine (MInterval head, MInterval tail)
1299 M17n.DebugPrint ("combining "); head.DumpOne (true, false);
1300 M17n.DebugPrint (" through "); tail.DumpOne (true, false);
1302 int from = head.From;
1304 // The nearest common parent of HEAD and TAIL.
1307 for (root = head; root.To + root.RightLength < to;
1308 root = root.Parent);
1310 M17n.DebugPrint (" common root is "); root.DumpOne (false, true);
1312 if (from < root.From)
1314 MInterval prev = root.Prev;
1318 M17n.DebugPrint ("merging "); prev.DumpOne (false, true);
1319 prev.vacate_node (prev.Left, root);
1322 if (prev.Left != null)
1323 prev = prev.Left.RightMost;
1327 root.update_from_to ();
1331 MInterval next = root.Next;
1335 M17n.DebugPrint ("merging "); next.DumpOne (false, true);
1336 next.vacate_node (next.Right, root);
1339 if (next.Right != null)
1340 next = next.Right.LeftMost;
1344 root.update_from_to ();
1348 public void MergeAfterChange (int start, int end)
1352 MInterval head = find_head (start), tail = head, i;
1354 if (start == head.From && start > 0)
1357 if (head.mergeable (i))
1360 while (tail.To < end)
1363 if (! tail.mergeable (i))
1366 combine (head, tail);
1367 i.update_from_to ();
1375 if (i == null || ! tail.mergeable (i))
1380 combine (head, tail);
1383 public void Pop (int start, int end)
1386 M17n.DebugPrint ("pop({0} {1}) at ", start, end); DumpOne (false, true);
1391 Left.Pop (start, end);
1394 Left.Pop (start, From);
1401 Right.Pop (start, end);
1404 Right.Pop (To, end);
1408 if (! Stack.IsEmpty)
1411 divide_left (start);
1418 public void PopSensitive (int start, int end)
1421 MInterval head = find_head (start);
1422 MInterval tail = find_tail (end);
1423 while (! head.Stack.IsEmpty && head.From > 0)
1425 MInterval prev = head.Prev;
1427 if (prev.Stack.IsEmpty || head.Stack.Val != prev.Stack.Val)
1431 while (! tail.Stack.IsEmpty && tail.To < mtext.Length)
1433 MInterval next = tail.Next;
1435 if (next.Stack.IsEmpty || tail.Stack.Val != next.Stack.Val)
1439 Pop (head.From, tail.To);
1442 private void DumpOne (bool with_prop, bool newline)
1444 DumpOne (with_prop, newline, false);
1447 private void DumpOne (bool with_prop, bool newline, bool force)
1449 if (force || M17n.debug)
1451 Console.Write ("#{0}({1} {2} {3}", ID, Length, From, To);
1453 foreach (MPlist p in Stack)
1454 Console.Write (" " + p.Val);
1455 Console.Write (")");
1457 Console.WriteLine ();
1459 throw new Exception ("Invalid interval length");
1463 public void Dump () { Dump (false); }
1465 public void Dump (bool force)
1467 if (force || M17n.debug)
1474 Console.Write (" ");
1475 DumpOne (true, false, force);
1482 get { return (Parent == null ? 0 : Parent.Depth + 1); }
1485 public void DumpNested (bool force)
1487 DumpNested (Key.ToString () + ":", force);
1490 public void DumpNested (string indent, bool force)
1492 if (force || M17n.debug)
1494 int indent_type = (Parent == null ? 1
1495 : Parent.Left == this ? 0 : 2);
1500 if (indent_type <= 1)
1501 Left.DumpNested (indent + " ", force);
1503 Left.DumpNested (indent + "| ", force);
1505 Console.Write (indent);
1506 if (indent_type == 0)
1507 Console.Write (".-");
1508 else if (indent_type == 2)
1509 Console.Write ("`-");
1510 DumpOne (true, true, true);
1513 if (indent_type >= 1)
1514 Right.DumpNested (indent + " ", force);
1516 Right.DumpNested (indent + "| ", force);
1522 private class MTextEnum : IEnumerator
1525 private int pos = -1;
1527 public MTextEnum (MText mt)
1532 public bool MoveNext ()
1535 return (pos < mt.nchars);
1538 public void Reset ()
1543 public object Current
1546 //if (pos < 0 || pos >= mt.nchars)
1547 //throw new InvalidOperationException ();