public enum Flags
{
None = 0x00,
- /// A text inserted before a character that has this property
- /// inherits this property. If the text already has properties
- /// of the same key, they are deleted.
- FrontSticky = 0x01,
- /// A text inserted after a character that has this property
- /// inherits this property. If the text already has properties
- /// of the same key, they are deleted.
- RearSticky = 0x02,
+
+ /// On inserting a text in between two characters, if the
+ /// preceding and following characters have Sticky properties of
+ /// the same key with same values, the inserted text inherits
+ /// those properties. In that case, properties of the inserted
+ /// text are overriden.
+ Sticky = 0x01, // 00000001
+
+ /// On inserting a text before a character, if the character has
+ /// FrontSticky properties, the inserted text inherits those
+ /// properties.
+ FrontSticky = 0x03, // 00000011
+
+ /// On inserting a text after a character, if the character has
+ /// RearSticky properties, the inserted text inherits those
+ /// properties.
+ RearSticky = 0x05, // 00000101
+
+ /// Like RearSticky, but if the inserted text inherits no
+ /// properties from the preceding character, it inherits
+ /// BothSticky properties from the following character if any.
+ BothSticky = 0x07, // 00000111
+
/// This property is deleted from a span of text if the span is
- /// modified (i.e. a character is changed, a text is inserted,
- /// some part is deleted). This propery is also deleted if a
- /// property of the same key is added, which means that this
- /// property is not stackable.
- Sensitive = 0x04,
+ /// modified (i.e. one of a character is changed, a text is
+ /// inserted, some part is deleted). Here, "span" means a
+ /// sequence of characters that has this property with the same
+ /// value. This property is also deleted if a property of the
+ /// same key is added, which means that this property is not
+ /// stackable. In addition this property is never merged with
+ /// the same value of preceding or following property. At last,
+ /// this property can't be sticky in any way.
+ Sensitive = 0x10, // 00010000
+
/// Like Sensitive but also this property is deleted from a span
- /// of text if a text just before the span is modified,
+ /// of text if a characeter just before the span is modified,
/// inserted, or deleted.
- FrontSensitive = 0x08,
+ FrontSensitive = 0x30, // 00110000
+
/// Like Sensitive but also this property is deleted from a span
- /// of text if a text just after the span is modified, inserted,
- /// or deleted.
- RearSensitive = 0x10
+ /// of text if a character just after the span is modified,
+ /// inserted, or deleted.
+ RearSensitive = 0x50, // 01010000
+
+ /// Same as (FrontSensitive | RearSensitive).
+ BothSensitive = 0x70, // 01110000
};
internal MSymbol key;
public static bool HasFlags (MSymbol key, Flags flags)
{
- return ((key.flags & flags) != Flags.None);
+ return ((key.flags & flags) == flags);
}
public override string ToString ()
intervals = new MPlist ();
}
+ public MText (byte[] str, int offset, int length)
+ {
+ sb = new StringBuilder (utf8.GetString (str, offset, length));
+ nchars = count_chars (sb);
+ intervals = new MPlist ();
+ }
+
public MText (String str)
{
sb = new StringBuilder (str);
intervals.Push (prop.key, root);
}
else
- root = (MInterval) p.Val;
-
- if (root.isSensitive)
- root.PopSensitive (from, to);
+ {
+ root = (MInterval) p.Val;
+ if (root.isSensitive)
+ {
+ root.PopSensitive (from, to);
+ root.MergeAfterChange (from, to);
+ root = (MInterval) p.Val;
+ if (M17n.debug)
+ DumpPropNested ();
+ }
+ }
root.Push (from, to, prop);
root.MergeAfterChange (from, to);
root.Balance ();
MProperty.Flags.RearSensitive) ; }
}
- public bool isAnySensitive
- {
- get { return MProperty.HasFlags (Key,
- (MProperty.Flags.Sensitive
- | MProperty.Flags.RearSensitive
- | MProperty.Flags.FrontSensitive)) ; }
- }
-
private void update_from_to ()
{
if (Parent == null)
{
MPlist p1, p2;
+ if (Stack.IsEmpty && i.Stack.IsEmpty)
+ return true;
+ if (isSensitive)
+ return false;
for (p1 = Stack, p2 = i.Stack; ! p1.IsEmpty && ! p2.IsEmpty;
p1 = p1.Next, p2 = p2.Next)
if (p1.Val != p2.Val)
MInterval head = find_head (start);
MInterval tail = find_tail (end);
+ M17n.DebugPrint ("Copying: {0}", copy);
+
if (! head.Stack.IsEmpty
- && (isAnySensitive && head.From < start
- || isFrontSensitive && ! first))
+ && (isSensitive && head.From < start
+ || (isFrontSensitive && ! first)))
{
+ M17n.DebugPrint (" clear head");
head = copy.find_head (0);
head.Stack.Clear ();
}
if (! tail.Stack.IsEmpty
- && (isAnySensitive && end < head.To
- || isRearSensitive && ! last))
+ && (isSensitive && end < tail.To
+ || (isRearSensitive && ! last)))
{
+ M17n.DebugPrint (" clear tail");
tail = copy.find_tail (copy.Length);
tail.Stack.Clear ();
}
- M17n.DebugPrint ("Copied: {0}\n", copy);
+ M17n.DebugPrint ("\n");
return copy;
}
len = 0;
if (Stack.IsEmpty
- && (isFrontSensitive
- || ((isSensitive || isRearSensitive) && i.From < start)))
+ && (isFrontSensitive || (isSensitive && i.From < start)))
{
- M17n.DebugPrint (" grafting {0}", i);
+ M17n.DebugPrint (" forward grafting {0}", i);
if (i.To < end)
len = i.To - start;
else
}
while (i != null && i.From < end && mergeable (i))
{
- M17n.DebugPrint (" grafting {0}", i);
+ M17n.DebugPrint (" forward grafting {0}", i);
len += i.To - i.From;
if (i.From < start)
len -= start - i.From;
len = 0;
if (Stack.IsEmpty
- && (isRearSensitive
- || ((isSensitive || isFrontSensitive) && end < i.To)))
+ && (isRearSensitive || (isSensitive && end < i.To)))
{
- M17n.DebugPrint (" grafting {0}", i);
+ M17n.DebugPrint (" backward grafting {0}", i);
if (i.From <= start)
len = end - start;
else
}
while (i != null && i.To <= start && mergeable (i))
{
- M17n.DebugPrint (" grafting {0}", i);
+ M17n.DebugPrint (" backward grafting {0}", i);
len += i.To - i.From;
if (end < i.To)
len -= i.To - end;
if (prev != null && isRearSticky && ! prev.Stack.IsEmpty)
{
prev.enlarge (end - start);
+ M17n.DebugPrint (" done\n");
return;
}
if (isFrontSticky && ! Stack.IsEmpty)
{
enlarge (end - start);
+ M17n.DebugPrint (" done\n");
return;
}
bool front_grafted = false, rear_grafted = false;
{
start += grafted;
if (start == end)
- return;
+ {
+ M17n.DebugPrint (" done\n");
+ return;
+ }
front_grafted = true;
}
if ((grafted = graft_backward (interval, start, end)) > 0)
{
end -= grafted;
if (start == end)
- return;
+ {
+ M17n.DebugPrint (" done\n");
+ return;
+ }
rear_grafted = true;
}
{
if (! Stack.IsEmpty)
{
- if (isSensitive || isFrontSensitive || isRearSensitive)
+ if (isSensitive)
Stack.Clear ();
else if (isFrontSticky || isRearSticky)
{
{
start += grafted;
if (start == end)
- return;
+ {
+ M17n.DebugPrint (" done\n");
+ return;
+ }
front_grafted = true;
pos += grafted;
}
{
end -= grafted;
if (start == end)
- return;
+ {
+ M17n.DebugPrint (" done\n");
+ return;
+ }
rear_grafted = true;
}
if (interval != null)
if (isRearSticky && ! Stack.IsEmpty)
{
enlarge (end - start);
+ M17n.DebugPrint (" done by enlarging this\n");
return;
}
if (next != null && isFrontSticky && ! next.Stack.IsEmpty)
{
+ M17n.DebugPrint (" next is {0}\n", next);
next.enlarge (end - start);
+ M17n.DebugPrint (" done by enlarging next\n");
return;
}
bool front_grafted = false, rear_grafted = false;
{
end -= grafted;
if (start == end)
- return;
+ {
+ M17n.DebugPrint (" done\n");
+ return;
+ }
rear_grafted = true;
}
if ((grafted = graft_forward (interval, start, end)) > 0)
{
start += grafted;
if (start == end)
- return;
+ {
+ M17n.DebugPrint (" done\n");
+ return;
+ }
front_grafted = true;
}
if (interval != null)
interval = interval.Copy (mtext, start, end,
front_grafted,
(rear_grafted
- || (next == null && end < interval.mtext.Length)));
+ || (next == null && end == interval.mtext.Length)));
else
interval = new MInterval (Key, mtext, end - start, null);
Left.Delete (start, end);
return;
}
- if (isSensitive || isFrontSensitive)
+ if (isSensitive)
Stack.Clear ();
Left.Delete (start, From);
To -= From - start;
Right.Delete (start, end);
return;
}
- if (isSensitive || isRearSensitive)
+ if (isSensitive)
Stack.Clear ();
Right.Delete (To, end);
end = To;
{
int len = end - start;
- if (isAnySensitive)
+ if (isSensitive)
Stack.Clear ();
for (MInterval i = this; i != null; i = i.Parent)
i.Length -= len;
end = To;
}
- if (! Stack.IsEmpty && isAnySensitive)
+ if (! Stack.IsEmpty && isSensitive)
Stack.Clear ();
if (start > From)
divide_left (start);
if (! Stack.IsEmpty)
{
- if (isAnySensitive)
+ if (isSensitive)
Stack.Clear ();
else
{
update_from_to ();
MInterval head = find_head (start);
MInterval tail = find_tail (end);
- while (! head.Stack.IsEmpty && head.From > 0)
- {
- MInterval prev = head.Prev;
-
- if (prev.Stack.IsEmpty || head.Stack.Val != prev.Stack.Val)
- break;
- head = head.Prev;
- }
- while (! tail.Stack.IsEmpty && tail.To < mtext.Length)
- {
- MInterval next = tail.Next;
-
- if (next.Stack.IsEmpty || tail.Stack.Val != next.Stack.Val)
- break;
- tail = tail.Next;
- }
Pop (head.From, tail.To);
}
public void DumpNested (bool force)
{
- DumpNested (Key.ToString () + ":", force);
+ DumpNested (" " + Key.ToString () + ":", force);
}
public void DumpNested (string indent, bool force)