ecc24eb66eb36d08fcd029c8d6fef7728b03c81a
[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       MText mt = new MText (mt1.sb);
98
99       mt.sb.Append (mt2.sb);
100       mt.nchars = mt1.nchars + mt2.nchars;
101       return mt;
102     }
103
104     private static bool surrogate_high_p (char c)
105     {
106       return (c >= 0xD800 && c < 0xDC00);
107     }
108
109     private static bool surrogate_low_p (char c)
110     {
111       return (c >= 0xDC00 && c < 0xE000);
112     }
113
114     private int inc_idx (int i)
115     {
116       return (i + (surrogate_high_p (sb[i]) ? 2 : 1));
117     }
118
119     private int dec_idx (int i)
120     {
121       return (i - (surrogate_low_p (sb[i - 1]) ? 2 : 1));
122     }
123
124     private int pos_to_idx (int pos)
125     {
126       int p, i;
127       bool forward;
128
129       if (pos < cache_pos)
130         {
131           if (cache_pos == cache_idx)
132             return cache_idx;
133           if (pos < cache_pos - pos)
134             {
135               p = i = 0;
136               forward = true;
137             }
138           else
139             {
140               p = cache_pos; i = cache_idx;
141               forward = false;
142             }
143         }
144       else
145         {
146           if (nchars - cache_pos == sb.Length - cache_idx)
147             return (cache_idx + pos - cache_pos);
148           if (pos - cache_pos < nchars - pos)
149             {
150               p = cache_pos; i = cache_idx;
151               forward = true;
152             }
153           else
154             {
155               p = nchars; i = sb.Length;
156               forward = false;
157             }
158         }
159       if (forward)
160         for (; p < pos; i = inc_idx (i), p++);
161       else
162         for (; p > pos; i = dec_idx (i), p--);
163       cache_pos = p;
164       cache_idx = i;
165       return i;
166     }
167
168     private readonly bool readonlyp;
169
170     private void insert (int pos, MText mt2, int from, int to)
171     {
172       if (pos != cache_pos)
173         pos = pos_to_idx (pos);
174
175     }
176
177     public int this[int i]
178     {
179       set {
180         if (i != cache_pos)
181           i = pos_to_idx (i);
182         if (value < 0x10000)
183           sb[i] = (char) value;
184         else
185           {
186             char high = (char) (0xD800 + ((i - 0x10000) >> 10));
187             char low = (char) (0xDC00 + ((i - 0x10000) & 0x3FF));
188
189             if (! surrogate_high_p (sb[i]))
190               sb.Insert (i, 0);
191             sb[i++] = high;
192             sb[i] = low;
193           }
194       }
195       get {
196         if (i != cache_pos)
197           i = pos_to_idx (i);
198         return (surrogate_high_p (sb[i])
199                 ? i = ((sb[i] - 0xD800) << 10) + (sb[i + 1] - 0xDC00) + 0x10000
200                 : sb[i]);
201       }
202     }
203
204     public MText dup ()
205     {
206       return (new MText (this.sb));
207     }
208
209     public MText ins (int pos, MText mt)
210     {
211       insert (pos, mt, 0, mt.nchars);
212       return this;
213     }
214
215     public MText ins (int pos, MText mt, int from, int to)
216     {
217       insert (pos, mt, from, to);
218       return this;
219     }
220   }
221
222   public class MTextProperty
223   {
224   }
225 }