*** empty log message ***
[m17n/m17n-lib-cs.git] / MText.cs
index 5c916f1..14a0696 100644 (file)
--- a/MText.cs
+++ b/MText.cs
@@ -115,7 +115,7 @@ namespace M17N.Core
     private int cache_idx;
     private MPlist intervals;
     private MPlist default_property;
-    private bool read_only;
+    private bool read_only = false;
 
     private static UTF8Encoding utf8 = new UTF8Encoding ();
 
@@ -124,7 +124,7 @@ namespace M17N.Core
       int len = str.Length, n = 0;
 
       for (int i = 0; i < len; i++, n++) 
-       if (surrogate_high_p (str[i]))
+       if (Char.IsHighSurrogate (str[i]))
          i++;
       return n;
     }
@@ -134,7 +134,7 @@ namespace M17N.Core
       int len = str.Length, n = 0;
 
       for (int i = 0; i < len; i++, n++) 
-       if (surrogate_high_p (str[i]))
+       if (Char.IsHighSurrogate (str[i]))
          i++;
       return n;
     }
@@ -173,6 +173,14 @@ namespace M17N.Core
        intervals = new MPlist ();
       }
 
+    public MText (int c, int len) : this ()
+      {
+       while (len-- > 0)
+         this.Cat (c);
+      }
+
+    public MText (int c) : this (c, 1) { }
+
     public static MText operator+ (object obj, MText mt)
     {
       if (obj is string)
@@ -219,24 +227,24 @@ namespace M17N.Core
 
     public override string ToString () { return sb.ToString (); }
 
-    private static bool surrogate_high_p (char c)
+    public static implicit operator MText (string str)
     {
-      return (c >= 0xD800 && c < 0xDC00);
+      return new MText (str);
     }
 
-    private static bool surrogate_low_p (char c)
+    public static explicit operator string (MText mt)
     {
-      return (c >= 0xDC00 && c < 0xE000);
+      return mt.ToString ();
     }
 
     private static int inc_idx (StringBuilder sb, int i)
     {
-      return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
+      return (i + (Char.IsHighSurrogate (sb[i]) ? 2 : 1));
     }
 
     private static int dec_idx (StringBuilder sb, int i)
     {
-      return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
+      return (i - (Char.IsLowSurrogate (sb[i - 1]) ? 2 : 1));
     }
 
     private static int pos_to_idx (MText mt, int pos)
@@ -250,7 +258,7 @@ namespace M17N.Core
       if (pos < mt.cache_pos)
        {
          if (mt.cache_pos == mt.cache_idx)
-           return mt.cache_idx;
+           return pos;
          if (pos < mt.cache_pos - pos)
            {
              p = i = 0;
@@ -371,7 +379,7 @@ namespace M17N.Core
        i = pos_to_idx (this, i);
        if (value < 0x10000)
          {
-           if (surrogate_high_p (sb[i]))
+           if (Char.IsHighSurrogate (sb[i]))
              sb.Remove (i, 1);
            sb[i] = (char) value;
          }
@@ -380,20 +388,32 @@ namespace M17N.Core
            char high = (char) (0xD800 + ((value - 0x10000) >> 10));
            char low = (char) (0xDC00 + ((value - 0x10000) & 0x3FF));
 
-           if (! surrogate_high_p (sb[i]))
+           if (! Char.IsHighSurrogate (sb[i]))
              sb.Insert (i, 0);
            sb[i] = high;
            sb[i + 1] = low;
          }
+       PopProp (i, i + 1);
       }
       get {
        i = pos_to_idx (this, i);
-       return (surrogate_high_p (sb[i])
+       return (Char.IsHighSurrogate (sb[i])
                ? ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
                : sb[i]);
       }
     }
 
+    public MText this[int from, int to]
+    {
+      set {
+       if (from < to)
+         Del (from, to);
+       if (value != null)
+         Ins (from, value);
+      }
+      get { return Dup (from, to); }
+    }
+
     public MText Dup ()
     {
       MText mt = new MText (sb.ToString ());
@@ -446,14 +466,23 @@ namespace M17N.Core
       return this;
     }
 
+    public MText Cat (MText mt, int from, int to)
+    {
+      insert (nchars, mt, from, to);
+      return this;
+    }
+
+    public MText Del ()
+    {
+      return Del (0, Length);
+    }
+
     public MText Del (int from, int to)
     {
       if (check_range (from, to, true))
        return this;
-
       sb.Remove (from, pos_to_idx (this, to) - pos_to_idx (this, from));
       nchars -= to - from;
-
       if (nchars > 0)
        foreach (MPlist plist in intervals)
          {
@@ -548,6 +577,29 @@ namespace M17N.Core
        }
     }
 
+    public void PopProp (int from, int to)
+    {
+      if (from < 0)
+       {
+         default_property = null;
+       }
+      else
+       {
+         if (check_range (from, to, true))
+           return;
+         for (MPlist p = intervals; ! p.IsEmpty; p = p.next)
+           {
+             MInterval root = (MInterval) p.Val;
+             root.PopAll (from, to);
+             root = (MInterval) p.Val;
+             if (M17n.debug)
+               DumpPropNested ();
+             root.MergeAfterChange (from, to);
+             root.Balance ();
+           }
+       }
+    }
+
     public void PopProp (int from, int to, MSymbol key)
     {
       if (from < 0)
@@ -582,6 +634,19 @@ namespace M17N.Core
        }
     }
 
+    public object FindProp (MSymbol key, int pos, out int from, out int to)
+    {
+      from = 0;
+      to = Length;
+      check_pos (pos, false);
+      
+      MInterval i = (MInterval) intervals.Get (key);
+      if (i != null
+         && (i = i.Find (pos, out from, out to)) != null)
+       return GetProp (from, key);
+      return null;
+    }
+
     public void DumpProp ()
     {
       Console.Write ("(");
@@ -899,6 +964,21 @@ namespace M17N.Core
        return Parent;
       }
 
+      public MInterval Find (int pos, out int from, out int to)
+      {
+       MInterval i = find_head (pos);
+
+       from = to = pos;
+       if (i.Stack.IsEmpty)
+         i = i.Next;
+       if (i != null)
+         {
+           from = i.From;
+           to = i.To;
+         }
+       return i;
+      }
+
       public MInterval Balance ()
       {
        MInterval i = this;
@@ -1646,6 +1726,46 @@ namespace M17N.Core
        Pop (head.From, tail.To);
       }
 
+      public void PopAll (int start, int end)
+      {
+       update_from_to ();
+       M17n.DebugPrint ("popall({0} {1}) at {2}\n", start, end, this);
+       if (start < From)
+         {
+           if (end <= From)
+             {
+               Left.PopAll (start, end);
+               return;
+             }
+           Left.PopAll (start, From);
+           start = From;
+         }
+       if (end > To)
+         {
+           if (start >= To)
+             {
+               Right.PopAll (start, end);
+               return;
+             }
+           Right.PopAll (To, end);
+           end = To;
+         }
+
+       if (! Stack.IsEmpty)
+         {
+           if (isSensitive)
+             Stack.Clear ();
+           else
+             {
+               if (start > From)
+                 divide_left (start);
+               if (end < To)
+                 divide_right (end);
+               Stack.Clear ();
+             }
+         }
+      }
+
       public override string ToString ()
       {
        string str = String.Format ("#{0}({1} {2} {3} [", ID, Length, From, To);