{
internal MSymbol key;
internal object val;
- private bool front_sticky;
- private bool rear_sticky;
+
+ [FlagsAttribute]
+ internal enum Flag : byte
+ {
+ None = 0,
+ FrontSticky = 1,
+ RearSticky = 2,
+ Sensitive = 4
+ };
+ internal Flag flags;
public MSymbol Key { get { return key; } }
public object Val { get { return val; } }
- public bool FrontSticky { get { return front_sticky; } }
- public bool RearSticky { get { return rear_sticky; } }
+ public bool FrontSticky
+ {
+ get { return (flags & Flag.FrontSticky) != Flag.None; }
+ }
+ public bool RearSticky
+ {
+ get { return (flags & Flag.RearSticky) != Flag.None; }
+ }
+ public bool Sensitive
+ {
+ get { return (flags & Flag.Sensitive) != Flag.None; }
+ }
public MTextProperty (MSymbol key, object val)
{
this.key = key;
this.val = val;
+ flags |= Flag.RearSticky;
}
public MTextProperty (MSymbol key, object val,
- bool front_sticky, bool rear_sticky)
+ bool front_sticky, bool rear_sticky, bool sensitive)
{
this.key = key;
this.val = val;
- this.front_sticky = front_sticky;
- this.rear_sticky = rear_sticky;
+ if (front_sticky)
+ flags |= Flag.FrontSticky;
+ if (rear_sticky)
+ flags |= Flag.RearSticky;
+ if (sensitive)
+ flags |= Flag.Sensitive;
}
}
return this.sb.ToString ().CompareTo (other.sb.ToString ());
}
- public override String ToString () { return sb.ToString (); }
+ public override String ToString () { return "\"" + sb.ToString () + "\""; }
private static bool surrogate_high_p (char c)
{
private int total_length;
private int from, to;
private MSymbol key;
- private Stack<MTextProperty> stack;
+ private MPlist stack;
private MInterval left, right, parent;
private MText mtext;
throw new Exception ("Invalid interval length");
this.key = key;
total_length = length;
- stack = new Stack<MTextProperty> ();
+ stack = new MPlist ();
}
public MInterval (MSymbol key, MText mt)
total_length = mt.sb.Length;
from = 0;
to = total_length;
- stack = new Stack<MTextProperty> ();
+ stack = new MPlist ();
}
public MTextProperty get (int pos)
{
MInterval i = find (pos);
- return (i.stack.Count > 0 ? i.stack.Peek () : null);
+ return (i.stack.IsEmpty ? null : (MTextProperty) i.stack.Val);
}
public MTextProperty get (int pos, out MTextProperty[] array)
{
MInterval i = find (pos);
- if (i.stack.Count == 0)
+ if (i.stack.IsEmpty)
{
array = null;
return null;
}
- array = i.stack.ToArray ();
- return i.stack.Peek ();
+ array = new MTextProperty[i.stack.Count];
+
+ int idx;
+ MPlist p;
+ for (idx = 0, p = i.stack; ! p.IsEmpty; idx++, p = p.Next)
+ array[idx] = (MTextProperty) p.Val;
+ return array[idx - 1];
}
- private MInterval (MSymbol key, int length, Stack<MTextProperty> stack)
+ private MInterval (MSymbol key, int length, MPlist stack)
{
this.key = key;
total_length = length;
from = 0;
to = total_length;
- stack = new Stack<MTextProperty> (stack);
+ this.stack = stack.Clone ();
}
-
private void update_from_to ()
{
if (parent != null)
get { return (right == null ? 0 : right.total_length); }
}
- private MInterval LeftMostNode
+ private MInterval left_most_node
{
- get { return (left == null ? this : left.LeftMostNode); }
+ get { return (left == null ? this : left.left_most_node); }
}
- private MInterval RightMostNode
+ private MInterval right_most_node
{
- get { return (right == null ? this : right.RightMostNode); }
+ get { return (right == null ? this : right.right_most_node); }
}
- private MInterval LeftNode {
+ private MInterval prev {
get {
MInterval i;
}
}
- private MInterval RightNode {
+ private MInterval next {
get {
MInterval i;
return interval;
}
+ private void remove_properties (MTextProperty.Flag flags)
+ {
+ for (MPlist p = stack; ! p.IsEmpty;)
+ {
+ MTextProperty prop = (MTextProperty) p.Val;
+
+ if ((prop.flags & flags) == flags)
+ p.pop ();
+ else
+ p = p.Next;
+ }
+ }
+
+ private void merge_properties (MPlist plist, MTextProperty.Flag flags)
+ {
+ if (left != null)
+ left.merge_properties (plist, flags);
+ if (right != null)
+ right.merge_properties (plist, flags);
+ for (MPlist p = plist; ! p.IsEmpty; p = p.Next)
+ {
+ MTextProperty prop = (MTextProperty) p.Val;
+
+ if ((prop.flags & flags) == flags
+ && stack.get (prop.Key) == null)
+ stack.push (prop.key, prop);
+ }
+ }
+
public void insert (int pos, MInterval interval)
{
update_from_to ();
- if (pos < from)
+ if (pos < from || (pos == from && left == null && pos > 0))
{
- LeftNode.insert (pos, interval);
+ prev.insert (pos, interval);
return;
}
- if (pos >= to)
+ if (pos > to || (pos == to && right == null && next != null))
{
- RightNode.insert (pos, interval);
+ next.insert (pos, interval);
return;
}
- if (pos > from)
+ if (pos > from && pos < to)
{
+ remove_properties (MTextProperty.Flag.Sensitive);
divide_right (pos).insert (pos, interval);
return;
}
-
- // POS == FROM
- if (left != null && LeftNode.stack.Count > 0)
+ if (pos == from)
{
- Stack<MTextProperty> s = new Stack<MTextProperty> ();
-
- foreach (MTextProperty p in LeftNode.stack)
- if (p.RearSticky)
- s.Push (p);
- if (s.Count > 0)
+ if (pos > 0)
{
- for (MInterval i = interval.LeftMostNode;
- i != null && i.stack.Count == 0;
- i = i.LeftNode)
- foreach (MTextProperty p in s)
- i.stack.Push (p);
+ prev.remove_properties
+ (MTextProperty.Flag.Sensitive|MTextProperty.Flag.RearSticky);
+ interval.merge_properties
+ (prev.stack, MTextProperty.Flag.RearSticky);
}
- }
- if (stack.Count > 0)
- {
- Stack<MTextProperty> s = new Stack<MTextProperty> ();
-
- foreach (MTextProperty p in stack)
- if (p.FrontSticky)
- s.Push (p);
- if (s.Count > 0)
+ remove_properties
+ (MTextProperty.Flag.Sensitive|MTextProperty.Flag.FrontSticky);
+ interval.merge_properties
+ (stack, MTextProperty.Flag.FrontSticky);
+
+ // INTERVAL is ready to insert.
+ //
+ // .-this-. ==> .-this-.
+ // left-. left-.
+ // child .-interval
+ // child
+
+ if (pos > 0)
{
- for (MInterval i = interval.RightMostNode;
- i != null && i.stack.Count == 0;
- i = i.RightNode)
- foreach (MTextProperty p in s)
- i.stack.Push (p);
+ MInterval i = left.right_most_node;
+
+ i.left = interval;
+ interval.parent = i;
+ for (; i != null; i = i.parent)
+ i.total_length += interval.total_length;
}
- }
-
- // INTERVAL is ready to insert.
- //
- // .-this-. ==> .-this-.
- // left-. left-.
- // child interval
- // child
+ else
+ {
+ left = interval;
- if (left != null)
- {
- MInterval i = left.RightMostNode;
-
- i.left = interval;
- interval.parent = i;
- for (; i != null; i = i.parent)
- i.total_length += interval.total_length;
+ for (MInterval i = this; i != null; i = i.parent)
+ i.total_length += interval.total_length;
+ }
}
- else
+ else // pos == to
{
- left = interval;
+ if (right != null)
+ {
+ MInterval left_most = right.left_most_node;
- for (MInterval i = this; i != null; i = i.parent)
- i.total_length += interval.total_length;
+ left_most.remove_properties
+ (MTextProperty.Flag.Sensitive|MTextProperty.Flag.FrontSticky);
+ interval.merge_properties
+ (stack, MTextProperty.Flag.FrontSticky);
+ }
+ remove_properties
+ (MTextProperty.Flag.Sensitive|MTextProperty.Flag.RearSticky);
+ interval.merge_properties
+ (stack, MTextProperty.Flag.RearSticky);
+
+ // INTERVAL is ready to insert.
+ //
+ // .-this-. ==> .-this-.
+ // .-right .-right
+ // child interval-.
+ // child
+
+ if (right != null)
+ {
+ MInterval i = right.left_most_node;
+
+ i.left = interval;
+ interval.parent = i;
+ for (; i != null; i = i.parent)
+ i.total_length += interval.total_length;
+ }
+ else
+ {
+ right = interval;
+
+ for (MInterval i = this; i != null; i = i.parent)
+ i.total_length += interval.total_length;
+ }
}
}
divide_left (from);
if (end < to)
divide_right (end);
- stack.Push (prop);
+ stack.push (prop.key, prop);
return prop;
}
}