X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=MText.cs;h=98cb0c5c753991a9722bba332cdd0f3f6cba4030;hb=727abe1e469396eaa63ceee4d5588bfa2493493b;hp=57a847bd85adb796ed2375e2dc905ea95afb0f7d;hpb=80a46f5fb11e98798ea0490008ec61cd36c9f5a5;p=m17n%2Fm17n-lib-cs.git diff --git a/MText.cs b/MText.cs index 57a847b..98cb0c5 100644 --- a/MText.cs +++ b/MText.cs @@ -53,7 +53,6 @@ namespace M17N.Core { this.key = key; this.val = val; - flags |= Flag.RearSticky; } public MTextProperty (MSymbol key, object val, @@ -252,6 +251,8 @@ namespace M17N.Core { check_pos (pos, true); + if (from == to) + return; int pos_idx = pos_to_idx (this, pos); int from_idx = pos_to_idx (mt2, from); int to_idx = pos_to_idx (mt2, to); @@ -464,7 +465,11 @@ namespace M17N.Core MPlist p = intervals.Find (key); if (p != null) - ((MInterval) p.Val).Pop (from, to); + { + MInterval root = (MInterval) p.Val; + root.Pop (from, to); + root.MergeAfterChange (from, to); + } } } @@ -547,7 +552,7 @@ namespace M17N.Core MPlist p; for (idx = 0, p = i.Stack; ! p.IsEmpty; idx++, p = p.Next) array[idx] = (MTextProperty) p.Val; - return array[idx - 1]; + return array[0]; } private MInterval (MSymbol key, MText mt, int length, MPlist stack) @@ -592,12 +597,22 @@ namespace M17N.Core private MInterval LeftMost { - get { return (Left == null ? this : Left.LeftMost); } + get { + if (Left == null) + return this; + Left.update_from_to (); + return Left.LeftMost; + } } private MInterval RightMost { - get { return (Right == null ? this : Right.RightMost); } + get { + if (Right == null) + return this; + Right.update_from_to (); + return Right.RightMost; + } } private MInterval Prev { @@ -605,12 +620,14 @@ namespace M17N.Core MInterval i; if (Left != null) - for (i = Left; i.Right != null; i = i.Right); + for (i = Left; i.Right != null; i = i.Right) + i.update_from_to (); else { MInterval child = this; for (i = Parent; i != null && i.Left == child; - child = i, i = i.Parent); + child = i, i = i.Parent) + i.update_from_to (); } return i; } @@ -621,12 +638,14 @@ namespace M17N.Core MInterval i; if (Right != null) - for (i = Right; i.Left != null; i = i.Left); + for (i = Right; i.Left != null; i = i.Left) + i.update_from_to (); else { MInterval child = this; for (i = Parent; i != null && i.Right == child; - child = i, i = i.Parent); + child = i, i = i.Parent) + i.update_from_to (); } return i; } @@ -974,7 +993,7 @@ namespace M17N.Core { update_from_to (); M17N.DebugPrint ("insert({0}) at {1} in ", interval.Length, pos); - DumpOne (false, true); + DumpOne (false, false); interval.set_mtext (mtext); @@ -1093,11 +1112,20 @@ namespace M17N.Core } else // (pos > To) Next.Insert (pos, interval); + M17N.DebugPrint (" done\n"); } private void vacate_node (MInterval interval) { - M17N.DebugPrint ("vacate #{0} to #{1}", ID, interval.ID); + vacate_node (interval, null); + } + + private void vacate_node (MInterval interval, MInterval stop) + { + if (interval != null) + M17N.DebugPrint ("vacate #{0} to #{1}\n", ID, interval.ID); + else + M17N.DebugPrint ("vacate #{0} to null\n", ID); if (interval != null) interval.Parent = Parent; if (Parent == null) @@ -1115,7 +1143,7 @@ namespace M17N.Core int diff = Length; if (interval != null) diff -= interval.Length; - for (MInterval i = Parent; i != null; i = i.Parent) + for (MInterval i = Parent; i != stop; i = i.Parent) i.Length -= diff; } } @@ -1208,74 +1236,93 @@ namespace M17N.Core Stack.Push (prop.key, prop); } - private bool try_merge_prev () + private static void merge_nodes (MInterval head, MInterval tail) { - MInterval prev = Prev; + M17N.DebugPrint ("merging "); head.DumpOne (true, false); + M17N.DebugPrint (" through "); tail.DumpOne (true, false); - if (! mergeable (prev)) - return false; + int from = head.From; + int to = tail.To; + MInterval root; - M17N.DebugPrint ("merging "); DumpOne (false, false); - M17N.DebugPrint (" with prev "); prev.DumpOne (false, true); - int len = prev.Length - prev.LeftLength; + for (root = head; root.To + root.RightLength < to; + root = root.Parent); + + M17N.DebugPrint (" common root is "); root.DumpOne (false, true); - // PREV is Left, Left.Right, ..., or Left....Right. - if (prev != Left) + if (from < root.From) { - if (prev.Left != null) - prev.Left.Parent = prev.Parent; - prev.Parent.Right = prev.Left; - while (prev.Parent != Left) + MInterval prev = root.Prev; + + while (true) { - prev.Length -= len; - prev = prev.Parent; + M17N.DebugPrint ("merging "); prev.DumpOne (false, true); + prev.vacate_node (prev.Left, root); + if (prev == head) + break; + if (prev.Left != null) + prev = prev.Left.RightMost; + else + prev = prev.Parent; } } - Left.Length -= len; - if (Left.Length == Left.LeftLength) + if (root.To < to) { - if (Left.Left != null) - Left.Left.Parent = this; - Left = Left.Left; + MInterval next = root.Next; + + while (true) + { + M17N.DebugPrint ("merging "); next.DumpOne (false, true); + next.vacate_node (next.Right, root); + if (next == tail) + break; + if (next.Right != null) + next = next.Right.LeftMost; + else + next = next.Parent; + } } - return true; } - private bool try_merge_next () + public void MergeAfterChange (int start, int end) { - MInterval next = Next; - - if (! mergeable (next)) - return false; - - M17N.DebugPrint ("merging "); DumpOne (false, false); - M17N.DebugPrint (" with next "); next.DumpOne (false, true); + update_from_to (); + if (start < From) + { + Prev.MergeAfterChange (start, end); + return; + } - int len = next.Length - next.RightLength; + MInterval head = this, tail = this, i; - // NEXT is Right, Right.Left, ..., or Right....Left. - if (next != Right) + if (start == From && start > 0) { - if (next.Right != null) - next.Right.Parent = next.Parent; - next.Parent.Left = next.Right; - while (next.Parent != Right) + i = Prev; + if (mergeable (i)) + head = i; + } + while (tail.To < end) + { + i = tail.Next; + if (! tail.mergeable (i)) { - next.Length -= len; - next = next.Parent; + if (head != tail) + merge_nodes (head, tail); + head = i; } + tail = i; } - Right.Length -= len; - if (Right.Length == Right.RightLength) + while (true) { - if (Right.Right != null) - Right.Right.Parent = this; - Right = Right.Right; + i = tail.Next; + if (i == null || ! tail.mergeable (i)) + break; + tail = i; } - return true; + if (head != tail) + merge_nodes (head, tail); } - public void Pop (int start, int end) { update_from_to (); @@ -1303,27 +1350,11 @@ namespace M17N.Core if (! Stack.IsEmpty) { - bool check_prev = start == From && start > 0; - bool check_next = end == To && end < mtext.Length; - - if (! check_prev) + if (start > From) divide_left (start); - if (! check_next) + if (end < To) divide_right (end); Stack.Pop (); - if (check_prev && Left != null) - check_prev = try_merge_prev () && (Left != null); - if (check_next && Right != null) - check_next = try_merge_next () && (Right != null); - if (check_prev) - { - if (Prev.try_merge_next () && check_next) - Prev.try_merge_next (); - } - else if (check_next) - { - Next.try_merge_prev (); - } } } @@ -1343,6 +1374,8 @@ namespace M17N.Core Console.Write (")"); if (newline) Console.WriteLine (); + if (Length <= 0) + throw new Exception ("Invalid interval length"); } } @@ -1368,16 +1401,6 @@ namespace M17N.Core get { return (Parent == null ? 0 : Parent.Depth + 1); } } - private void DumpNestedOne () - { - int depth; - MInterval i; - - for (depth = 0, i = this; i.Parent != null; depth++, i = i.Parent) - Console.Write (" "); - DumpOne (true, true); - } - public void DumpNested (bool force) { DumpNested ("", force); @@ -1402,12 +1425,12 @@ namespace M17N.Core Console.Write (indent + ".-"); else if (indent_type == 2) Console.Write (indent + "`-"); - DumpOne (true, true); + DumpOne (true, true, true); if (Right != null) { if (indent_type >= 1) Right.DumpNested (indent + " ", force); - else if (indent_type == 2) + else Right.DumpNested (indent + "| ", force); } }