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 MTextProperty
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). If this property is also FrontSticky
41 /// (or RearSticky), text insertion just before (or after) the
42 /// span also deletes this property from the span of text.
49 public MSymbol Key { get { return key; } }
50 public object Val { get { return val; } }
52 public MTextProperty (MSymbol key, object val)
58 public override string ToString ()
60 return key.ToString () + ":" + val;
64 public class MText : IEnumerable, IEquatable<MText>, IComparable<MText>
67 public enum MTextFormat format;
69 private StringBuilder sb;
71 private int cache_pos;
72 private int cache_idx;
73 private MPlist intervals;
74 private MPlist default_property;
75 private bool read_only;
77 private static UTF8Encoding utf8 = new UTF8Encoding ();
79 private static int count_chars (String str)
81 int len = str.Length, n = 0;
83 for (int i = 0; i < len; i++, n++)
84 if (surrogate_high_p (str[i]))
89 private static int count_chars (StringBuilder str)
91 int len = str.Length, n = 0;
93 for (int i = 0; i < len; i++, n++)
94 if (surrogate_high_p (str[i]))
101 sb = new StringBuilder ();
102 intervals = new MPlist ();
105 public MText (byte[] str)
107 sb = new StringBuilder (utf8.GetString (str));
108 nchars = count_chars (sb);
109 intervals = new MPlist ();
112 public MText (String str)
114 sb = new StringBuilder (str);
115 nchars = count_chars (str);
116 intervals = new MPlist ();
119 public MText (StringBuilder str)
122 nchars = count_chars (str);
123 intervals = new MPlist ();
126 public static MText operator+ (MText mt1, MText mt2)
128 MText mt = new MText ();
130 mt.sb.Append (mt1.sb);
131 mt.sb.Append (mt2.sb);
132 mt.nchars = mt1.nchars + mt2.nchars;
137 public bool ReadOnly { get { return read_only; } }
138 public int Length { get { return nchars; } }
142 // for IEnumerable interface
143 public IEnumerator GetEnumerator() { return new MTextEnum (this); }
145 // for IEquatable interface
146 public bool Equals (MText other) { return this.sb.Equals (other.sb); }
148 // for IComparable interface
149 public int CompareTo (MText other)
151 return this.sb.ToString ().CompareTo (other.sb.ToString ());
154 public override String ToString () { return "\"" + sb.ToString () + "\""; }
156 private static bool surrogate_high_p (char c)
158 return (c >= 0xD800 && c < 0xDC00);
161 private static bool surrogate_low_p (char c)
163 return (c >= 0xDC00 && c < 0xE000);
166 private static int inc_idx (StringBuilder sb, int i)
168 return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
171 private static int dec_idx (StringBuilder sb, int i)
173 return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
176 private static int pos_to_idx (MText mt, int pos)
178 if (pos == mt.cache_pos)
184 if (pos < mt.cache_pos)
186 if (mt.cache_pos == mt.cache_idx)
188 if (pos < mt.cache_pos - pos)
195 p = mt.cache_pos; i = mt.cache_idx;
201 if (mt.nchars - mt.cache_pos == mt.sb.Length - mt.cache_idx)
202 return (mt.cache_idx + pos - mt.cache_pos);
203 if (pos - mt.cache_pos < mt.nchars - pos)
205 p = mt.cache_pos; i = mt.cache_idx;
210 p = mt.nchars; i = mt.sb.Length;
215 for (; p < pos; i = inc_idx (mt.sb, i), p++);
217 for (; p > pos; i = dec_idx (mt.sb, i), p--);
223 private void check_pos (int pos, bool tail_ok)
225 if (pos < 0 || (tail_ok ? pos > nchars : pos >= nchars))
226 throw new Exception ("Invalid MText position:" + pos);
229 private bool check_range (int from, int to, bool zero_ok)
231 if (from < 0 || (zero_ok ? from > to : from >= to)
233 throw new Exception ("Invalid MText range");
237 private void insert (int pos, MText mt2, int from, int to)
239 check_pos (pos, true);
243 int pos_idx = pos_to_idx (this, pos);
244 int from_idx = pos_to_idx (mt2, from);
245 int to_idx = pos_to_idx (mt2, to);
247 sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
250 foreach (MPlist plist in intervals)
252 MPlist p = mt2.intervals.Find (plist.Key);
256 i = new MInterval (plist.Key, this, to - from);
258 i = ((MInterval) p.Val).Copy (this, from, to);
259 ((MInterval) plist.Val).Insert (pos, i);
261 foreach (MPlist plist in mt2.intervals)
262 if (intervals.Find (plist.Key) == null)
264 MInterval i = (((MInterval) plist.Val).Copy (this, from, to));
265 intervals.Push (plist.Key, i);
269 private void insert (int pos, int c)
271 check_pos (pos, true);
273 int pos_idx = pos_to_idx (this, pos);
278 sb.Insert (pos_idx, ch);
282 char high = (char) (0xD800 + ((c - 0x10000) >> 10));
283 char low = (char) (0xDC00 + ((c - 0x10000) & 0x3FF));
284 sb.Insert (pos_idx, low);
285 sb.Insert (pos_idx, high);
288 foreach (MPlist plist in intervals)
289 ((MInterval) plist.Val).Insert (pos,
290 new MInterval (plist.Key, this, 1));
293 public int this[int i]
296 i = pos_to_idx (this, i);
299 if (surrogate_high_p (sb[i]))
301 sb[i] = (char) value;
305 char high = (char) (0xD800 + ((value - 0x10000) >> 10));
306 char low = (char) (0xDC00 + ((value - 0x10000) & 0x3FF));
308 if (! surrogate_high_p (sb[i]))
315 i = pos_to_idx (this, i);
316 return (surrogate_high_p (sb[i])
317 ? ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
324 MText mt = new MText (sb.ToString ());
326 foreach (MPlist p in intervals)
327 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, 0, Length));
331 public MText Dup (int from, int to)
333 if (check_range (from, to, true))
336 MText mt = new MText (sb.ToString ().Substring (pos_to_idx (this, from),
337 pos_to_idx (this, to)));
338 foreach (MPlist p in intervals)
339 mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, from, to));
343 public MText Ins (int pos, int c)
349 public MText Ins (int pos, MText mt)
351 insert (pos, mt, 0, mt.nchars);
355 public MText Ins (int pos, MText mt, int from, int to)
357 insert (pos, mt, from, to);
361 public MText Cat (int c)
367 public MText Del (int from, int to)
369 if (check_range (from, to, true))
372 sb.Remove (from, pos_to_idx (this, to) - pos_to_idx (this, from));
376 foreach (MPlist plist in intervals)
377 ((MInterval) plist.Val).Delete (from, to);
379 intervals = new MPlist ();
385 public object GetProp (int pos, MSymbol key)
387 check_pos (pos, false);
389 MInterval i = (MInterval) intervals.Get (key);
393 MTextProperty prop = i.Get (pos);
394 return (prop != null ? prop.Val : null);
397 public object GetProp (int pos, MSymbol key, out MTextProperty prop)
399 check_pos (pos, false);
401 MInterval i = (MInterval) intervals.Get (key);
403 return (prop = null);
405 return (prop != null ? prop.Val : null);
408 public object GetProp (int pos, MSymbol key, out MTextProperty[] array)
410 check_pos (pos, false);
412 MInterval i = (MInterval) intervals.Get (key);
414 return (array = null);
415 MTextProperty prop = i.Get (pos, out array);
416 return (prop != null ? prop.Val : null);
419 public void PushProp (int from, int to, MSymbol key, object val)
421 if (! check_range (from, to, true))
422 PushProp (from, to, new MTextProperty (key, val));
425 public void PushProp (int from, int to, MTextProperty prop)
429 if (default_property == null)
430 default_property = new MPlist ();
431 default_property.Push (prop.key, prop.val);
435 if (check_range (from, to, true))
438 MPlist p = intervals.Find (prop.key);
443 root = new MInterval (prop.key, this);
444 intervals.Push (prop.key, root);
447 root = (MInterval) p.Val;
449 root.Push (from, to, prop);
453 public void PopProp (int from, int to, MSymbol key)
457 if (default_property == null)
459 MPlist p = default_property.Find (key);
466 if (check_range (from, to, true))
469 MPlist p = intervals.Find (key);
473 MInterval root = (MInterval) p.Val;
475 root.MergeAfterChange (from, to);
480 public void DumpProp ()
483 foreach (MPlist p in intervals)
484 ((MInterval) p.Val).Dump (true);
485 Console.WriteLine (")");
488 public void DumpPropNested ()
490 Console.WriteLine ("total length = {0}", Length);
491 foreach (MPlist p in intervals)
492 ((MInterval) p.Val).DumpNested (true);
495 private class MInterval
497 // position: 0 1 2 3 4 5 6 7
498 // | A | B | C | D | E F | G |
499 // interval |---|---|---|<->|-------|---|
500 // |---|<->|---| |<----->|---|
504 // [3 (1 2)] [3 (4 6)]
505 // [1 (0 1)] [2 (2 3)] [1 (6 7)]
507 private static int count = 0;
510 private int From, To;
512 private MPlist Stack;
513 private MInterval Left, Right, Parent;
516 public MInterval (MSymbol key, MText mt, int length)
519 throw new Exception ("Invalid interval length");
523 Stack = new MPlist ();
527 public MInterval (MSymbol key, MText mt)
531 Length = mt.sb.Length;
534 Stack = new MPlist ();
538 public MTextProperty Get (int pos)
540 MInterval i = find (pos);
542 return (i.Stack.IsEmpty ? null : (MTextProperty) i.Stack.Val);
545 public MTextProperty Get (int pos, out MTextProperty[] array)
547 MInterval i = find (pos);
554 array = new MTextProperty[i.Stack.Count];
558 for (idx = 0, p = i.Stack; ! p.IsEmpty; idx++, p = p.Next)
559 array[idx] = (MTextProperty) p.Val;
563 private MInterval (MSymbol key, MText mt, int length, MPlist stack)
570 Stack = stack.Clone ();
574 private bool isRearSticky
576 get { return ((Key.TextPropertyFlags & MTextProperty.Flags.RearSticky)
577 != MTextProperty.Flags.None); }
580 private bool isFrontSticky
582 get { return ((Key.TextPropertyFlags & MTextProperty.Flags.FrontSticky)
583 != MTextProperty.Flags.None); }
586 private bool isSensitive
588 get { return ((Key.TextPropertyFlags & MTextProperty.Flags.Sensitive)
589 != MTextProperty.Flags.None); }
592 private void update_from_to ()
597 To = Length - RightLength;
599 else if (Parent.Left == this)
601 From = Parent.From - Length + LeftLength;
602 To = Parent.From - RightLength;
606 From = Parent.To + LeftLength;
607 To = Parent.To + Length - RightLength;
611 private int LeftLength
613 get { return (Left == null ? 0 : Left.Length); }
616 private int RightLength
618 get { return (Right == null ? 0 : Right.Length); }
621 private MInterval LeftMost
627 return Left.LeftMost;
631 private MInterval RightMost
637 return Right.RightMost;
641 private MInterval Prev {
646 for (i = Left; i.Right != null; i = i.Right)
650 MInterval child = this;
651 for (i = Parent; i != null && i.Left == child;
652 child = i, i = i.Parent);
658 private MInterval Next {
663 for (i = Right; i.Left != null; i = i.Left)
667 MInterval child = this;
668 for (i = Parent; i != null && i.Right == child;
669 child = i, i = i.Parent);
675 private MInterval find (int pos)
679 return Left.find (pos);
681 return Right.find (pos);
685 private bool mergeable (MInterval i)
689 for (p1 = Stack, p2 = i.Stack; ! p1.IsEmpty && ! p2.IsEmpty;
690 p1 = p1.Next, p2 = p2.Next)
691 if (p1.Val != p2.Val)
693 return (p1.IsEmpty && p2.IsEmpty);
696 // p-. or .-p p-. or .-p
697 // .-this-. .-right-.
698 // left .-right-. -> .-this-. c2
700 private MInterval promote_right ()
702 int right_length = Right.Length;
706 mtext.intervals.Put (Key, Right);
707 else if (Parent.Left == this)
710 Parent.Right = Right;
711 Right.Parent = Parent;
717 Parent.Length += Length;
718 Length -= right_length;
722 Parent.Length -= c1.Length;
728 // p-. or .-p p-. or .-p
730 // .-left-. .-right-. -> c1 .-this-.
732 private MInterval promote_left ()
734 int left_length = Left.Length;
738 mtext.intervals.Put (Key, Left);
739 else if (Parent.Left == this)
743 Left.Parent = Parent;
749 Parent.Length += Length;
750 Length -= left_length;
754 Parent.Length -= c1.Length;
760 private MInterval balance ()
767 // .-left-. .-right-.
769 int diff = i.LeftLength - i.RightLength;
774 new_diff = (i.Length - i.LeftLength
775 + i.Left.RightLength - i.Left.LeftLength);
776 if (Math.Abs (new_diff) >= diff)
778 i = i.promote_left ();
783 new_diff = (i.Length - i.RightLength
784 + i.Right.LeftLength - i.Right.RightLength);
785 if (Math.Abs (new_diff) >= diff)
787 i = i.promote_right ();
794 public MInterval Copy (MText mt, int start, int end)
796 MInterval copy, left_copy = null, right_copy = null;
803 return Left.Copy (mt, start, end);
804 left_copy = Left.Copy (mt, start, From);
809 return Right.Copy (mt, start, end);
810 right_copy = Right.Copy (mt, To, end);
813 copy = new MInterval (Key, null, end - start, Stack);
818 if (isRearSticky && start < From && ! Left.Stack.IsEmpty)
820 else if (isFrontSticky && end > To && ! Right.Stack.IsEmpty)
823 if (left_copy != null)
825 copy.Left = left_copy;
826 left_copy.Parent = copy;
828 if (right_copy != null)
830 copy.Right = right_copy;
831 right_copy.Parent = copy;
839 private MInterval divide_right (int pos)
841 MInterval interval = new MInterval (Key, mtext, To - pos, Stack);
843 M17n.DebugPrint ("divide-right({0}) at ", pos); DumpOne (false, true);
847 interval.Right = Right;
848 Right.Parent = interval;
849 interval.Length += Right.Length;
851 interval.Parent = this;
859 private MInterval divide_left (int pos)
861 MInterval interval = new MInterval (Key, mtext, pos - From, Stack);
863 M17n.DebugPrint ("divide-left({0}) at ", pos); DumpOne (false, true);
867 interval.Left = Left;
868 Left.Parent = interval;
869 interval.Length += Left.Length;
871 interval.Parent = this;
876 private void remove_properties (MTextProperty.Flags flags)
879 && (Key.TextPropertyFlags & flags) == flags)
883 private void inherit_front_properties (MPlist plist)
885 for (MInterval i = LeftMost; i != null; i = i.Next)
889 for (MPlist p = plist; ! p.IsEmpty; p = p.Next)
891 MTextProperty prop = (MTextProperty) p.Val;
893 if ((p.Key.TextPropertyFlags & MTextProperty.Flags.RearSticky)
894 == MTextProperty.Flags.RearSticky)
895 i.Stack.Add (prop.key, prop);
900 private void inherit_rear_properties (MPlist plist)
902 for (MInterval i = RightMost; i != null; i = i.Prev)
906 for (MPlist p = plist; ! p.IsEmpty; p = p.Next)
908 MTextProperty prop = (MTextProperty) p.Val;
910 if ((p.Key.TextPropertyFlags & MTextProperty.Flags.FrontSticky)
911 == MTextProperty.Flags.FrontSticky)
912 i.Stack.Add (prop.key, prop);
917 private MInterval delete_node_forward ()
921 int len = Length - RightLength;
923 for (MInterval i = Parent; i != null; i = i.Parent)
925 if (Parent.Left == this)
928 Parent.Right = Right;
933 Right.Parent = Parent;
934 return Right.LeftMost;
939 private MInterval delete_node_backward ()
943 int len = Length - LeftLength;
945 for (MInterval i = Parent; i != null; i = i.Parent)
947 if (Parent.Left == this)
955 Left.Parent = Parent;
956 return Left.RightMost;
961 private void set_mtext (MText mt)
967 Right.set_mtext (mt);
970 private MInterval graft (MInterval interval, bool forward, out int len)
977 i = interval.LeftMost;
982 len += i.Length - i.RightLength;
983 i = i.delete_node_forward ();
988 i = interval.RightMost;
993 len += i.Length - i.LeftLength;
994 i = i.delete_node_backward ();
1002 M17n.DebugPrint ("grafted {0} in ", len); DumpOne (false, true);
1003 for (MInterval prev = this, ii = this.Parent; ii != null;
1004 prev = ii, ii = ii.Parent)
1007 if (prev == ii.Left)
1014 while (i.Parent != null) i = i.Parent;
1018 public void Insert (int pos, MInterval interval)
1021 M17n.DebugPrint ("insert({0}) at {1} in ", interval.Length, pos);
1022 DumpOne (false, false);
1024 interval.set_mtext (mtext);
1027 Prev.Insert (pos, interval);
1028 else if (pos == From)
1030 MInterval prev = Prev;
1036 prev.Insert (pos, interval);
1039 prev.remove_properties
1040 (MTextProperty.Flags.Sensitive|MTextProperty.Flags.RearSticky);
1041 interval.inherit_front_properties (prev.Stack);
1044 (MTextProperty.Flags.Sensitive|MTextProperty.Flags.FrontSticky);
1045 interval.inherit_rear_properties (Stack);
1048 interval = graft (interval, false, out len);
1049 if (interval != null && prev != null)
1050 interval = prev.graft (interval, true, out len);
1051 if (interval != null)
1057 // .-this-. ==> .-this-.
1069 interval.Parent = i;
1070 for (; i != null; i = i.Parent)
1071 i.Length += interval.Length;
1076 remove_properties (MTextProperty.Flags.Sensitive);
1079 interval = graft (interval, true, out len);
1081 if (interval != null)
1082 interval = graft (interval, false, out len);
1083 if (interval != null)
1086 Right.Left = interval;
1087 interval.Parent = Right;
1088 for (MInterval i = Right; i != null; i = i.Parent)
1089 i.Length += interval.Length;
1094 MInterval next = Next;
1100 next.Insert (pos, interval);
1103 next.remove_properties
1104 (MTextProperty.Flags.Sensitive|MTextProperty.Flags.FrontSticky);
1105 interval.inherit_rear_properties (next.Stack);
1108 (MTextProperty.Flags.Sensitive|MTextProperty.Flags.RearSticky);
1109 interval.inherit_front_properties (Stack);
1112 interval = graft (interval, true, out len);
1113 if (interval != null && next != null)
1114 interval = next.graft (interval, false, out len);
1115 if (interval != null)
1121 // .-this-. ==> .-this-.
1134 interval.Parent = i;
1135 for (; i != null; i = i.Parent)
1136 i.Length += interval.Length;
1140 Next.Insert (pos, interval);
1141 M17n.DebugPrint (" done\n");
1144 private void vacate_node (MInterval interval)
1146 vacate_node (interval, null);
1149 private void vacate_node (MInterval interval, MInterval stop)
1151 if (interval != null)
1152 M17n.DebugPrint ("vacate #{0} to #{1}\n", ID, interval.ID);
1154 M17n.DebugPrint ("vacate #{0} to null\n", ID);
1155 if (interval != null)
1156 interval.Parent = Parent;
1160 mtext.intervals.Put (Key, interval);
1164 if (this == Parent.Right)
1165 Parent.Right = interval;
1167 Parent.Left = interval;
1170 if (interval != null)
1171 diff -= interval.Length;
1172 for (MInterval i = Parent; i != stop; i = i.Parent)
1177 public void Delete (int start, int end)
1180 M17n.DebugPrint ("delete({0} {1}) from ", start, end); DumpOne (false, true);
1185 Left.Delete (start, end);
1188 Left.Delete (start, From);
1190 end -= From - start;
1197 Right.Delete (start, end);
1200 Right.Delete (To, end);
1203 if (start == From && end == To)
1215 for (i = Right; i.Left != null; i = i.Left)
1216 i.Length += Left.Length;
1217 i.Length += Left.Length;
1221 vacate_node (Right);
1226 int len = end - start;
1228 for (MInterval i = this; i != null; i = i.Parent)
1233 public void Push (int start, int end, MTextProperty prop)
1236 M17n.DebugPrint ("push({0} {1}) at ", start, end); DumpOne (false, true);
1241 Left.Push (start, end, prop);
1244 Left.Push (start, From, prop);
1251 Right.Push (start, end, prop);
1254 Right.Push (To, end, prop);
1259 divide_left (start);
1262 Stack.Push (prop.key, prop);
1265 private static void merge_nodes (MInterval head, MInterval tail)
1267 M17n.DebugPrint ("merging "); head.DumpOne (true, false);
1268 M17n.DebugPrint (" through "); tail.DumpOne (true, false);
1270 int from = head.From;
1274 for (root = head; root.To + root.RightLength < to;
1275 root = root.Parent);
1277 M17n.DebugPrint (" common root is "); root.DumpOne (false, true);
1279 if (from < root.From)
1281 MInterval prev = root.Prev;
1285 M17n.DebugPrint ("merging "); prev.DumpOne (false, true);
1286 prev.vacate_node (prev.Left, root);
1289 if (prev.Left != null)
1290 prev = prev.Left.RightMost;
1297 MInterval next = root.Next;
1301 M17n.DebugPrint ("merging "); next.DumpOne (false, true);
1302 next.vacate_node (next.Right, root);
1305 if (next.Right != null)
1306 next = next.Right.LeftMost;
1313 public void MergeAfterChange (int start, int end)
1318 Prev.MergeAfterChange (start, end);
1322 MInterval head = this, tail = this, i;
1324 if (start == From && start > 0)
1330 while (tail.To < end)
1333 if (! tail.mergeable (i))
1336 merge_nodes (head, tail);
1344 if (i == null || ! tail.mergeable (i))
1349 merge_nodes (head, tail);
1352 public void Pop (int start, int end)
1355 M17n.DebugPrint ("pop({0} {1}) at ", start, end); DumpOne (false, true);
1360 Left.Pop (start, end);
1363 Left.Pop (start, From);
1370 Right.Pop (start, end);
1373 Right.Pop (To, end);
1377 if (! Stack.IsEmpty)
1380 divide_left (start);
1387 private void DumpOne (bool with_prop, bool newline)
1389 DumpOne (with_prop, newline, false);
1392 private void DumpOne (bool with_prop, bool newline, bool force)
1394 if (force || M17n.debug)
1396 Console.Write ("#{0}({1} {2} {3}", ID, Length, From, To);
1398 foreach (MPlist p in Stack)
1399 Console.Write (" " + p.Val);
1400 Console.Write (")");
1402 Console.WriteLine ();
1404 throw new Exception ("Invalid interval length");
1408 public void Dump () { Dump (false); }
1410 public void Dump (bool force)
1412 if (force || M17n.debug)
1419 Console.Write (" ");
1420 DumpOne (true, false, force);
1427 get { return (Parent == null ? 0 : Parent.Depth + 1); }
1430 public void DumpNested (bool force)
1432 DumpNested ("", force);
1435 public void DumpNested (string indent, bool force)
1437 if (force || M17n.debug)
1439 int indent_type = (Parent == null ? 1
1440 : Parent.Left == this ? 0 : 2);
1445 if (indent_type <= 1)
1446 Left.DumpNested (indent + " ", force);
1448 Left.DumpNested (indent + "| ", force);
1450 if (indent_type == 0)
1451 Console.Write (indent + ".-");
1452 else if (indent_type == 2)
1453 Console.Write (indent + "`-");
1454 DumpOne (true, true, true);
1457 if (indent_type >= 1)
1458 Right.DumpNested (indent + " ", force);
1460 Right.DumpNested (indent + "| ", force);
1466 private class MTextEnum : IEnumerator
1469 private int pos = -1;
1471 public MTextEnum (MText mt)
1476 public bool MoveNext ()
1479 return (pos < mt.nchars);
1482 public void Reset ()
1487 public object Current
1490 //if (pos < 0 || pos >= mt.nchars)
1491 //throw new InvalidOperationException ();