*** empty log message ***
[m17n/m17n-lib-cs.git] / MText.cs
1 using System;
2 using System.Text;
3 using M17N.Core;
4
5 namespace M17N.Core
6 {
7 #if false
8   public enum MTextFormat
9   {
10     MTEXT_FORMAT_US_ASCII,
11     MTEXT_FORMAT_UTF_8,
12     MTEXT_FORMAT_UTF_16BE,
13     MTEXT_FORMAT_UTF_16LE,
14     MTEXT_FORMAT_UTF_32BE,
15     MTEXT_FORMAT_UTF_32LE,
16   }
17 #endif
18
19   public class MText
20   {
21 #if false
22     public enum MTextFormat format;
23 #endif
24
25     private class MTextPlist : MPlist
26     {
27       public class MInterval
28       {
29         MPlist stack;
30         int nprops;
31         public int start, end;
32         public MInterval prev, next;
33       }
34
35       MInterval head, tail;
36
37       public MTextPlist (MText mt)
38       {
39         head = tail = new MInterval ();
40         head.start = 0;
41         head.end = mt.sb.Length;
42       }
43     }
44
45     private StringBuilder sb;
46     private int nchars;
47     private int cache_pos;
48     private int cache_idx;
49     private MTextPlist plist;
50
51     private static UTF8Encoding utf8 = new UTF8Encoding ();
52     private static UTF32Encoding utf32 = new UTF32Encoding (true, false);
53
54     private static int count_chars (String str)
55     {
56       int len = str.Length, n = 0;
57
58       for (int i = 0; i < len; i++) 
59         n += surrogate_high_p (str[i]) ? 2 : 1;
60       return n;
61     }
62
63     private static int count_chars (StringBuilder str)
64     {
65       int len = str.Length, n = 0;
66
67       for (int i = 0; i < len; i++) 
68         n += surrogate_high_p (str[i]) ? 2 : 1;
69       return n;
70     }
71
72     public MText ()
73     {
74       sb = new StringBuilder ();
75     }
76
77     public MText (byte[] str)
78     {
79       sb = new StringBuilder (utf8.GetString (str));
80       nchars = count_chars (sb);
81     }
82
83     public MText (String str)
84     {
85       sb = new StringBuilder (str);
86       nchars = count_chars (str);
87     }
88
89     public MText (StringBuilder str)
90     {
91       sb = str;
92       nchars = count_chars (str);
93     }
94
95     public static MText operator+ (MText mt1, MText mt2)
96     {
97       return new MText (mt1.sb + mt2.sb);
98     }
99
100     private static bool surrogate_high_p (char c)
101     {
102       return (c >= 0xD800 && c < 0xDC00);
103     }
104
105     private static bool surrogate_low_p (char c)
106     {
107       return (c >= 0xDC00 && c < 0xE000);
108     }
109
110     private int inc_idx (int i)
111     {
112       return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
113     }
114
115     private int dec_idx (int i)
116     {
117       return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
118     }
119
120     private int pos_to_idx (int pos)
121     {
122       int p, i;
123       bool forward;
124
125       if (pos < cache_pos)
126         {
127           if (cache_pos == cache_idx)
128             return cache_idx;
129           if (pos < cache_pos - pos)
130             {
131               p = i = 0;
132               forward = true;
133             }
134           else
135             {
136               p = cache_pos; i = cache_idx;
137               forward = false;
138             }
139         }
140       else
141         {
142           if (nchars - cache_pos == sb.Length - cache_idx)
143             return (cache_idx + pos - cache_pos);
144           if (pos - cache_pos < nchars - pos)
145             {
146               p = cache_pos; i = cache_idx;
147               forward = true;
148             }
149           else
150             {
151               p = nchars; i = sb.Length;
152               forward = false;
153             }
154         }
155       if (forward)
156         for (; p < pos; i = inc_idx (i), p++);
157       else
158         for (; p > pos; i = dec_idx (i), p--);
159       cache_pos = p;
160       cache_idx = i;
161       return i;
162     }
163
164     public int this[int i]
165     {
166       set {
167         if (i != cache_pos)
168           i = pos_to_idx (i);
169         if (value < 0x10000)
170           sb[i] = (char) value;
171         else
172           {
173             char high = (char) (0xD800 + ((i - 0x10000) >> 10));
174             char low = (char) (0xDC00 + ((i - 0x10000) & 0x3FF));
175
176             if (! surrogate_high_p (sb[i]))
177               sb.Insert (i, 0);
178             sb[i++] = high;
179             sb[i] = low;
180           }
181       }
182       get {
183         if (i != cache_pos)
184           i = pos_to_idx (i);
185         return (surrogate_high_p (sb[i])
186                 ? i = ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
187                 : sb[i]);
188       }
189     }
190   }
191
192   public class MTextProperty
193   {
194   }
195 }