intervals = new MPlist ();
}
+ public static MText operator+ (object obj, MText mt)
+ {
+ if (obj is string)
+ return new MText ((string) obj) + mt;
+ throw new Exception ("Unknown object type: " + obj.GetType());
+ }
+
public static MText operator+ (MText mt1, MText mt2)
{
MText mt = new MText ();
return mt;
}
+ public static MText operator+ (string str, MText mt)
+ {
+ MText mtnew = new MText (str);
+
+ mtnew.sb.Append (mt.sb);
+ mtnew.nchars += mt.nchars;
+ return mtnew;
+ }
+
// Public properties
public bool ReadOnly { get { return read_only; } }
public int Length { get { return nchars; } }
{
check_pos (pos, true);
+ if (M17n.debug)
+ {
+ Console.Write ("inserting {0} to {1} of ", from, to);
+ mt2.DumpPropNested ();
+ }
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);
-
- sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
- nchars += to - from;
-
foreach (MPlist plist in intervals)
{
MPlist p = mt2.intervals.Find (plist.Key);
- MInterval i;
+ MInterval i = p == null ? null : (MInterval) p.Val;
- if (p == null)
- i = new MInterval (plist.Key, this, to - from);
- else
- i = ((MInterval) p.Val).Copy (this, from, to);
- ((MInterval) plist.Val).Insert (pos, i);
+ ((MInterval) plist.Val).Insert (pos, i, from, to);
}
foreach (MPlist plist in mt2.intervals)
if (intervals.Find (plist.Key) == null)
{
- MInterval i = (((MInterval) plist.Val).Copy (this, from, to));
- intervals.Push (plist.Key, i);
+ MInterval root;
+
+ if (nchars == 0)
+ root = ((MInterval) plist.Val).Copy (this, from, to);
+ else
+ {
+ root = new MInterval (plist.Key, this);
+ root.Insert (pos, (MInterval) plist.Val, from, to);
+ }
+ intervals.Push (plist.Key, root);
}
+
+ int pos_idx = pos_to_idx (this, pos);
+ int from_idx = pos_to_idx (mt2, from);
+ int to_idx = pos_to_idx (mt2, to);
+
+ sb.Insert (pos_idx, mt2.sb.ToString (from_idx, to_idx - from_idx));
+ nchars += to - from;
}
private void insert (int pos, int c)
}
nchars++;
foreach (MPlist plist in intervals)
- ((MInterval) plist.Val).Insert (pos,
- new MInterval (plist.Key, this, 1));
+ ((MInterval) plist.Val).Insert (pos, null, 0, 1);
}
public int this[int i]
{
if (check_range (from, to, true))
return new MText ();
+ int from_idx = pos_to_idx (this, from);
+ int len = pos_to_idx (this, to) - from_idx;
+ MText mt = new MText (sb.ToString ().Substring (from_idx, len));
- MText mt = new MText (sb.ToString ().Substring (pos_to_idx (this, from),
- pos_to_idx (this, to)));
foreach (MPlist p in intervals)
mt.intervals.Add (p.Key, ((MInterval) p.Val).Copy (mt, from, to));
return mt;
foreach (MPlist plist in intervals)
((MInterval) plist.Val).Delete (from, to);
else
- intervals = new MPlist ();
+ intervals.Clear ();
if (M17n.debug)
DumpPropNested ();
return this;
ID = count++;
}
+ /// POS must be smaller than Length;
public MTextProperty Get (int pos)
{
MInterval i = find (pos);
+ if (i.To == pos)
+ i = i.Next;
return (i.Stack.IsEmpty ? null : (MTextProperty) i.Stack.Val);
}
+ /// POS must be smaller than Length;
public MTextProperty Get (int pos, out MTextProperty[] array)
{
MInterval i = find (pos);
+ if (i.To == pos)
+ i = i.Next;
if (i.Stack.IsEmpty)
{
array = null;
Length = length;
From = 0;
To = Length;
- Stack = stack.Clone ();
+ Stack = stack == null ? new MPlist () : stack.Clone ();
ID = count++;
}
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 ();
i.update_from_to ();
+ }
else
{
MInterval child = this;
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 ();
i.update_from_to ();
+ }
else
{
MInterval child = this;
update_from_to ();
if (pos < From)
return Left.find (pos);
- if (pos >= To)
+ if (pos > To)
return Right.find (pos);
return this;
}
copy = new MInterval (Key, null, end - start, Stack);
copy.mtext = mt;
-
- if (isSensitive)
- {
- if (isRearSticky && start < From && ! Left.Stack.IsEmpty)
- Stack.Clear ();
- else if (isFrontSticky && end > To && ! Right.Stack.IsEmpty)
- Stack.Clear ();
- }
+ if (isSensitive && (From < start || end < To))
+ copy.Stack.Clear ();
if (left_copy != null)
{
copy.Left = left_copy;
return interval;
}
- private void remove_properties (MTextProperty.Flags flags)
- {
- if (! Stack.IsEmpty
- && (Key.TextPropertyFlags & flags) == flags)
- Stack.Clear ();
- }
-
- private void inherit_front_properties (MPlist plist)
+ private void set_mtext (MText mt)
{
- for (MInterval i = LeftMost; i != null; i = i.Next)
- {
- if (! Stack.IsEmpty)
- break;
- for (MPlist p = plist; ! p.IsEmpty; p = p.Next)
- {
- MTextProperty prop = (MTextProperty) p.Val;
-
- if ((p.Key.TextPropertyFlags & MTextProperty.Flags.RearSticky)
- == MTextProperty.Flags.RearSticky)
- i.Stack.Add (prop.key, prop);
- }
- }
+ mtext = mt;
+ if (Left != null)
+ Left.set_mtext (mt);
+ if (Right != null)
+ Right.set_mtext (mt);
}
- private void inherit_rear_properties (MPlist plist)
+ private void enlarge (int len)
{
- for (MInterval i = RightMost; i != null; i = i.Prev)
+ Length += len;
+ To += len;
+ for (MInterval prev = this, i = this.Parent; i != null;
+ prev = i, i = i.Parent)
{
- if (! Stack.IsEmpty)
- break;
- for (MPlist p = plist; ! p.IsEmpty; p = p.Next)
+ i.Length += len;
+ if (prev == i.Left)
{
- MTextProperty prop = (MTextProperty) p.Val;
-
- if ((p.Key.TextPropertyFlags & MTextProperty.Flags.FrontSticky)
- == MTextProperty.Flags.FrontSticky)
- i.Stack.Add (prop.key, prop);
+ i.From += len;
+ i.To += len;;
}
}
}
- private MInterval delete_node_forward ()
+ private int graft_forward (MInterval interval, int start, int end)
{
- if (Parent != null)
- {
- int len = Length - RightLength;
-
- for (MInterval i = Parent; i != null; i = i.Parent)
- i.Length -= len;
- if (Parent.Left == this)
- Parent.Left = Right;
- else
- Parent.Right = Right;
- }
-
- if (Right != null)
- {
- Right.Parent = Parent;
- return Right.LeftMost;
- }
- return Parent;
- }
+ int len;
- private MInterval delete_node_backward ()
- {
- if (Parent != null)
+ if (! Stack.IsEmpty && isRearSticky)
+ len = end - start;
+ else if (interval == null)
+ len = Stack.IsEmpty ? end - start : 0;
+ else
{
- int len = Length - LeftLength;
+ MInterval i = interval.find (start);
- for (MInterval i = Parent; i != null; i = i.Parent)
- i.Length -= len;
- if (Parent.Left == this)
- Parent.Left = Left;
- else
- Parent.Right = Left;
+ if (i.To == start && i.Right != null)
+ i = i.Next;
+ len = 0;
+ while (i != null && mergeable (i))
+ {
+ M17n.DebugPrint (" grafting "); i.DumpOne (false, false);
+ len += i.To - i.From;
+ if (i.From < start)
+ len -= start - i.From;
+ if (i.To >= end)
+ {
+ len -= i.To - end;
+ break;
+ }
+ i = i.Next;
+ }
}
- if (Left != null)
- {
- Left.Parent = Parent;
- return Left.RightMost;
- }
- return Parent;
+ M17n.DebugPrint (" grafted {0} in ", len); DumpOne (false, true);
+ if (len > 0)
+ enlarge (len);
+ return len;
}
- private void set_mtext (MText mt)
+ private int graft_backward (MInterval interval, int start, int end)
{
- mtext = mt;
- if (Left != null)
- Left.set_mtext (mt);
- if (Right != null)
- Right.set_mtext (mt);
- }
-
- private MInterval graft (MInterval interval, bool forward, out int len)
- {
- MInterval i;
+ int len;
- len = 0;
- if (forward)
- {
- i = interval.LeftMost;
- while (i != null)
- {
- if (! mergeable (i))
- break;
- len += i.Length - i.RightLength;
- i = i.delete_node_forward ();
- }
- }
+ if (! Stack.IsEmpty && isFrontSticky)
+ len = end - start;
+ else if (interval == null)
+ len = Stack.IsEmpty ? end - start : 0;
else
{
- i = interval.RightMost;
- while (i != null)
- {
- if (! mergeable (i))
- break;
- len += i.Length - i.LeftLength;
- i = i.delete_node_backward ();
- }
- }
+ MInterval i = interval.find (end);
- if (len == 0)
- return interval;
- Length += len;
- To += len;
- M17n.DebugPrint ("grafted {0} in ", len); DumpOne (false, true);
- for (MInterval prev = this, ii = this.Parent; ii != null;
- prev = ii, ii = ii.Parent)
- {
- ii.Length += len;
- if (prev == ii.Left)
+ if (i.From == end && i.Left != null)
+ i = i.Prev;
+ len = 0;
+ while (i != null && mergeable (i))
{
- ii.From += len;
- ii.To += len;;
+ M17n.DebugPrint (" grafting "); i.DumpOne (false, false);
+ len += i.To - i.From;
+ if (end < i.To)
+ len -= i.To - end;
+ if (i.From <= start)
+ {
+ len -= start - i.From;
+ break;
+ }
+ i = i.Prev;
}
}
- if (i != null)
- while (i.Parent != null) i = i.Parent;
- return i;
+
+ M17n.DebugPrint (" grafted {0} in ", len); DumpOne (false, true);
+ if (len > 0)
+ enlarge (len);
+ return len;
}
- public void Insert (int pos, MInterval interval)
+ public void Insert (int pos, MInterval interval, int start, int end)
{
update_from_to ();
- M17n.DebugPrint ("insert({0}) at {1} in ", interval.Length, pos);
- DumpOne (false, false);
- interval.set_mtext (mtext);
+ M17n.DebugPrint ("insert({0} to {1}) at {2} in ", start, end, pos);
+ DumpOne (false, false);
if (pos < From)
- Prev.Insert (pos, interval);
+ Left.Insert (pos, interval, start, end);
else if (pos == From)
{
- MInterval prev = Prev;
-
- if (prev != null)
+ if (Left != null)
{
- if (Left == null)
- {
- prev.Insert (pos, interval);
- return;
- }
- prev.remove_properties
- (MTextProperty.Flags.Sensitive|MTextProperty.Flags.RearSticky);
- interval.inherit_front_properties (prev.Stack);
+ MInterval prev = Prev;
+
+ if (prev.isSensitive && prev.isRearSticky)
+ prev.Stack.Clear ();
+ start += prev.graft_forward (interval, start, end);
}
- remove_properties
- (MTextProperty.Flags.Sensitive|MTextProperty.Flags.FrontSticky);
- interval.inherit_rear_properties (Stack);
-
- int len;
- interval = graft (interval, false, out len);
- if (interval != null && prev != null)
- interval = prev.graft (interval, true, out len);
- if (interval != null)
+ if (isSensitive && isFrontSticky)
+ Stack.Clear ();
+ if (start < end)
{
- MInterval i;
-
- if (Left != null)
+ end -= graft_backward (interval, start, end);
+ if (start < end)
{
- // .-this-. ==> .-this-.
- // left-. .-left-.
- // child child-.
- // interval
- i = Left.RightMost;
- i.Right = interval;
- }
- else
- {
- Left = interval;
- i = this;
+ if (interval != null)
+ interval = interval.Copy (mtext, start, end);
+ else
+ interval = new MInterval (Key, mtext, end - start, null);
+
+ MInterval i;
+ if (Left != null)
+ {
+ // .-this-. ==> .-this-.
+ // left-. .-left-.
+ // child child-.
+ // interval
+ i = Left.RightMost;
+ i.Right = interval;
+ }
+ else
+ {
+ Left = interval;
+ i = this;
+ }
+ interval.Parent = i;
+ for (; i != null; i = i.Parent)
+ i.Length += interval.Length;
}
- interval.Parent = i;
- for (; i != null; i = i.Parent)
- i.Length += interval.Length;
}
}
else if (pos < To)
{
- remove_properties (MTextProperty.Flags.Sensitive);
+ if (isSensitive)
+ Stack.Clear ();
- int len;
- interval = graft (interval, true, out len);
+ int len = graft_forward (interval, start, end);
+ start += len;
pos += len;
- if (interval != null)
- interval = graft (interval, false, out len);
- if (interval != null)
+ if (start < end)
{
- divide_right (pos);
- Right.Left = interval;
- interval.Parent = Right;
- for (MInterval i = Right; i != null; i = i.Parent)
- i.Length += interval.Length;
+ end -= graft_backward (interval, start, end);
+ if (start < end)
+ {
+ if (interval != null)
+ interval = interval.Copy (mtext, start, end);
+ else
+ interval = new MInterval (Key, mtext, end - start, null);
+
+ divide_right (pos);
+ Right.Left = interval;
+ interval.Parent = Right;
+ for (MInterval i = Right; i != null; i = i.Parent)
+ i.Length += interval.Length;
+ }
}
}
else if (pos == To)
{
- MInterval next = Next;
-
- if (next != null)
+ if (Right != null)
{
- if (Right == null)
- {
- next.Insert (pos, interval);
- return;
- }
- next.remove_properties
- (MTextProperty.Flags.Sensitive|MTextProperty.Flags.FrontSticky);
- interval.inherit_rear_properties (next.Stack);
+ MInterval next = Next;
+
+ if (next.isSensitive && next.isFrontSticky)
+ next.Stack.Clear ();
+ end -= next.graft_backward (interval, start, end);
}
- remove_properties
- (MTextProperty.Flags.Sensitive|MTextProperty.Flags.RearSticky);
- interval.inherit_front_properties (Stack);
-
- int len;
- interval = graft (interval, true, out len);
- if (interval != null && next != null)
- interval = next.graft (interval, false, out len);
- if (interval != null)
+ if (isSensitive && isRearSticky)
+ Stack.Clear ();
+ if (start < end)
{
- MInterval i;
-
- if (Right != null)
+ start += graft_forward (interval, start, end);
+ if (start < end)
{
- // .-this-. ==> .-this-.
- // .-right .-right
- // child .-child
- // interval
+ if (interval != null)
+ interval = interval.Copy (mtext, start, end);
+ else
+ interval = new MInterval (Key, mtext, end - start, null);
- i = Right.LeftMost;
- i.Left = interval;
- }
- else
- {
- Right = interval;
- i = this;
+ MInterval i;
+ if (Right != null)
+ {
+ // .-this-. ==> .-this-.
+ // .-right .-right
+ // child .-child
+ // interval
+
+ i = Right.LeftMost;
+ i.Left = interval;
+ }
+ else
+ {
+ Right = interval;
+ i = this;
+ }
+ interval.Parent = i;
+ for (; i != null; i = i.Parent)
+ i.Length += interval.Length;
}
- interval.Parent = i;
- for (; i != null; i = i.Parent)
- i.Length += interval.Length;
}
}
else // (pos > To)
- Next.Insert (pos, interval);
+ Next.Insert (pos, interval, start, end);
M17n.DebugPrint (" done\n");
}
Stack.Push (prop.key, prop);
}
- private static void merge_nodes (MInterval head, MInterval tail)
+ /// Combine intervals between HEAD and TAIL (both inclusive) to
+ /// the common parent of HEAD and TAIL while assuming that the
+ /// intervals are mergeable.
+ private static void combine (MInterval head, MInterval tail)
{
M17n.DebugPrint ("merging "); head.DumpOne (true, false);
M17n.DebugPrint (" through "); tail.DumpOne (true, false);
int from = head.From;
int to = tail.To;
+ // The nearest common parent of HEAD and TAIL.
MInterval root;
for (root = head; root.To + root.RightLength < to;
if (! tail.mergeable (i))
{
if (head != tail)
- merge_nodes (head, tail);
+ combine (head, tail);
head = i;
}
tail = i;
tail = i;
}
if (head != tail)
- merge_nodes (head, tail);
+ combine (head, tail);
}
public void Pop (int start, int end)
public void DumpNested (bool force)
{
- DumpNested ("", force);
+ DumpNested (Key.ToString () + ":", force);
}
public void DumpNested (string indent, bool force)
else
Left.DumpNested (indent + "| ", force);
}
+ Console.Write (indent);
if (indent_type == 0)
- Console.Write (indent + ".-");
+ Console.Write (".-");
else if (indent_type == 2)
- Console.Write (indent + "`-");
+ Console.Write ("`-");
DumpOne (true, true, true);
if (Right != null)
{