OSDN Git Service

7a412cfb97e9028c5a8974245815ad9feebf82b3
[bbk/bchanf.git] / src / control / texteditor_insertfilter.c
1 /*
2  * texteditor_insertfilter.c
3  *
4  * Copyright (c) 2014 project bchan
5  *
6  * This software is provided 'as-is', without any express or implied
7  * warranty. In no event will the authors be held liable for any damages
8  * arising from the use of this software.
9  *
10  * Permission is granted to anyone to use this software for any purpose,
11  * including commercial applications, and to alter it and redistribute it
12  * freely, subject to the following restrictions:
13  *
14  * 1. The origin of this software must not be misrepresented; you must not
15  *    claim that you wrote the original software. If you use this software
16  *    in a product, an acknowledgment in the product documentation would be
17  *    appreciated but is not required.
18  *
19  * 2. Altered source versions must be plainly marked as such, and must not be
20  *    misrepresented as being the original software.
21  *
22  * 3. This notice may not be removed or altered from any source
23  *    distribution.
24  *
25  */
26
27 #include        "texteditor_insertfilter.h"
28
29 #include        <bstdio.h>
30
31 #include        <tad/taditerator.h>
32 #include        <tad/tadstack.h>
33
34 #ifdef BCHAN_CONFIG_DEBUG
35 # define DP(arg) printf arg
36 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
37 #else
38 # define DP(arg) /**/
39 # define DP_ER(msg, err) /**/
40 #endif
41
42 #if 0
43 #define DP_STATE(s) printf("%s\n", s)
44 #else
45 #define DP_STATE(s) /**/
46 #endif
47
48 LOCAL Bool texteditor_insertfilter_stackfilter(texteditor_insertfilter_t *filter, taditerator_result *result)
49 {
50         W nestlevel;
51         TADSTACK_DATATYPE type;
52
53         for (;;) {
54                 taditerator_next2(&filter->iterator, result);
55                 if (result->type == TADITERATOR_RESULTTYPE_END) {
56                         break;
57                 }
58
59                 if (result->type == TADITERATOR_RESULTTYPE_CHARCTOR) {
60                         tadstack_inputcharactor(&filter->tadstack, result->segment);
61                 } else if (result->type == TADITERATOR_RESULTTYPE_SEGMENT) {
62                         tadstack_inputvsegment(&filter->tadstack, result->segment, result->data, result->segsize);
63                 }
64
65                 nestlevel = tadstack_nestlevel(&filter->tadstack);
66                 if (nestlevel > 0) {
67                         continue;
68                 }
69                 type = tadstack_currentdata(&filter->tadstack);
70                 if (type != TADSTACK_DATATYPE_TEXT) {
71                         continue;
72                 }
73
74                 return True;
75         }
76
77         return False;
78 }
79
80 struct texteditor_insertfilter_innerresult_ {
81         enum {
82                 INNERRESULT_VARIABLE,
83                 INNERRESULT_STRING,
84                 INNERRESULT_LANGCODE,
85         } type;
86         UB *data;
87         W len;
88         struct {
89                 UB segid;
90                 UW len;
91                 UB *data;
92         } variable;
93 };
94 typedef struct texteditor_insertfilter_innerresult_ texteditor_insertfilter_innerresult;
95
96 LOCAL Bool texteditor_insertfilter_langcode(texteditor_insertfilter_t *filter, texteditor_insertfilter_innerresult *result)
97 {
98         taditerator_result iter_result;
99         Bool reading_lang = False, cont;
100         TC *lang_start = NULL;
101
102         for (;;) {
103                 cont = texteditor_insertfilter_stackfilter(filter, &iter_result);
104                 if (cont == False) {
105                         break;
106                 }
107
108                 if (reading_lang != False) {
109                         if (iter_result.type != TADITERATOR_RESULTTYPE_CHARCTOR) {
110                                 /* format error */
111                                 break;
112                         }
113                         if (lang_start == NULL) {
114                                 break;
115                         }
116                         if (iter_result.segment == 0xFEFE) {
117                                 continue;
118                         }
119                         result->type = INNERRESULT_LANGCODE;
120                         result->data = (UB*)lang_start;
121                         result->len = (iter_result.pos - lang_start + 1) * sizeof(TC);
122                         TCtotadlangcode((TC*)result->data, result->len / sizeof(TC), &filter->current.lang);
123                         reading_lang = False;
124                         lang_start = NULL;
125                 }
126
127                 if (iter_result.type == TADITERATOR_RESULTTYPE_CHARCTOR) {
128                         if ((iter_result.segment & 0xFF00) == 0xFE00) {
129                                 if (iter_result.segment == 0xFEFE) {
130                                         reading_lang = True;
131                                         lang_start = iter_result.pos;
132                                 } else {
133                                         result->type = INNERRESULT_LANGCODE;
134                                         result->data = (UB*)iter_result.pos;
135                                         result->len = sizeof(TC);
136                                         TCtotadlangcode((TC*)result->data, result->len / sizeof(TC), &filter->current.lang);
137                                         return True;
138                                 }
139                         } else {
140                                 result->type = INNERRESULT_STRING;
141                                 result->data = (UB*)iter_result.pos;
142                                 result->len = sizeof(TC);
143                                 return True;
144                         }
145                 } else if (iter_result.type == TADITERATOR_RESULTTYPE_SEGMENT) {
146                         result->type = INNERRESULT_VARIABLE;
147                         result->data = (UB*)iter_result.pos;
148                         if (iter_result.vseg.l->len == 0xFFFF) {
149                                 result->len = 2 + 2 + 4 + iter_result.vseg.l->llen;
150                         } else {
151                                 result->len = 2 + 2 + iter_result.vseg.l->len;
152                         }
153                         result->variable.segid = iter_result.segment & 0xFF;
154                         result->variable.len = iter_result.segsize;
155                         result->variable.data = iter_result.data;
156                         return True;
157                 }
158         }
159
160         return False;
161 }
162
163 LOCAL Bool texteditor_insertfilter_chratio(texteditor_insertfilter_t *filter, texteditor_insertfilter_innerresult *result)
164 {
165         Bool cont;
166         UB subid;
167
168         for (;;) {
169                 cont = texteditor_insertfilter_langcode(filter, result);
170                 if (cont == False) {
171                         break;
172                 }
173
174                 if (result->type != INNERRESULT_VARIABLE) {
175                         return True;
176                 }
177
178                 if (result->variable.segid != TS_TFONT) {
179                         continue;
180                 }
181                 if (result->variable.len < 6) {
182                         continue;
183                 }
184                 subid = *(UH*)result->variable.data >> 8;
185                 if (subid != 3) {
186                         continue;
187                 }
188
189                 filter->current.w_ratio = *((UH*)result->variable.data + 5);
190
191                 return True;
192         }
193
194         return False;
195 }
196
197 /* */
198
199 LOCAL Bool texteditor_insertfilter_w_ratio_isZenkaku(RATIO w_ratio)
200 {
201         UB a,b;
202
203         a = w_ratio >> 8;
204         b = w_ratio & 0xFF;
205
206         if (b == 0) {
207                 return True;
208         }
209         if (a == b) {
210                 return True;
211         }
212         return False;
213 }
214
215 LOCAL Bool texteditor_insertfilter_w_ratio_isSystemScript(tadlangcode *lang)
216 {
217         return tadlangcodecmpTC((TC[]){0xFE21}, 1, lang);
218 }
219
220 /* */
221
222 LOCAL TC texteditor_insertfilter_systemlangcode[] = { 0xFE21 };
223 #define TEXTEDITOR_INSERTFILTER_SYSTEMLANGCODE_LENGTH 1
224
225 LOCAL TC textediter_insertfilter_zenkakufusen[] = { 0xFFA2, 0x0006, 0x0300, 0x0101, 0x0101 };
226 LOCAL TC textediter_insertfilter_hankakufusen[] = { 0xFFA2, 0x0006, 0x0300, 0x0101, 0x0102 };
227 #define TEXTEDITOR_INSERTFILTER_FUSEN_LENGTH 5
228
229 LOCAL VOID texteditor_insertfilter_setresult_systemlangcode(texteditor_insertfilter_result *result)
230 {
231         result->data = (UB*)texteditor_insertfilter_systemlangcode;
232         result->len = TEXTEDITOR_INSERTFILTER_SYSTEMLANGCODE_LENGTH * sizeof(TC);
233 }
234
235 LOCAL VOID texteditor_insertfilter_setresult_firstlangcode(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
236 {
237         result->len = tadlangcodetoTC(&filter->first.lang, filter->buffer, TEXTEDITOR_INSERTFILTER_TEXTBUFFER_SIZE) * sizeof(TC);
238         result->data = (UB*)filter->buffer;
239 }
240
241 LOCAL VOID texteditor_insertfilter_setresult_zenkakufusen(texteditor_insertfilter_result *result)
242 {
243         result->data = (UB*)textediter_insertfilter_zenkakufusen;
244         result->len = TEXTEDITOR_INSERTFILTER_FUSEN_LENGTH * sizeof(TC);
245 }
246
247 LOCAL VOID texteditor_insertfilter_setresult_hankakufusen(texteditor_insertfilter_result *result)
248 {
249         result->data = (UB*)textediter_insertfilter_hankakufusen;
250         result->len = TEXTEDITOR_INSERTFILTER_FUSEN_LENGTH * sizeof(TC);
251 }
252
253 /* */
254
255 LOCAL Bool texteditor_insertfilter_next_terminate(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
256 {
257         Bool ok, zen;
258
259         if (filter->first.w_ratio != filter->current.w_ratio) {
260                 filter->state = TEXTEDITOR_INSTERTFILTER_STATE_LAST_LANGCODE;
261                 zen = texteditor_insertfilter_w_ratio_isZenkaku(filter->first.w_ratio);
262                 if (zen == False) {
263                         texteditor_insertfilter_setresult_hankakufusen(result);
264                 } else {
265                         texteditor_insertfilter_setresult_zenkakufusen(result);
266                 }
267                 return True;
268         }
269         ok = tadlangcodecmp(&filter->first.lang, &filter->current.lang);
270         if (ok == False) {
271                 filter->state = TEXTEDITOR_INSTERTFILTER_STATE_LAST;
272                 texteditor_insertfilter_setresult_firstlangcode(filter, result);
273                 return True;
274         }
275
276         return False;
277 }
278
279 LOCAL Bool texteditor_insertfilter_next_state_start(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
280 {
281         texteditor_insertfilter_innerresult inner_result;
282         Bool cont, ok;
283
284         ok = texteditor_insertfilter_w_ratio_isZenkaku(filter->first.w_ratio);
285         if (ok == False) {
286                 filter->state = TEXTEDITOR_INSTERTFILTER_STATE_FIRST_LANGCODE;
287                 texteditor_insertfilter_setresult_zenkakufusen(result);
288                 return True;
289         }
290         ok = texteditor_insertfilter_w_ratio_isSystemScript(&filter->first.lang);
291         if (ok == False) {
292                 filter->state = TEXTEDITOR_INSTERTFILTER_STATE_RUNNING;
293                 texteditor_insertfilter_setresult_systemlangcode(result);
294                 return True;
295         }
296
297         cont = texteditor_insertfilter_chratio(filter, &inner_result);
298         if (cont == False) {
299                 return texteditor_insertfilter_next_terminate(filter, result);
300         }
301
302         filter->state = TEXTEDITOR_INSTERTFILTER_STATE_RUNNING;
303         result->data = inner_result.data;
304         result->len = inner_result.len;
305
306         return True;
307 }
308
309 LOCAL Bool texteditor_insertfilter_next_state_langcode(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
310 {
311         texteditor_insertfilter_innerresult inner_result;
312         Bool cont, ok;
313
314         ok = texteditor_insertfilter_w_ratio_isSystemScript(&filter->first.lang);
315         if (ok == False) {
316                 filter->state = TEXTEDITOR_INSTERTFILTER_STATE_RUNNING;
317                 texteditor_insertfilter_setresult_systemlangcode(result);
318                 return True;
319         }
320
321         cont = texteditor_insertfilter_chratio(filter, &inner_result);
322         if (cont == False) {
323                 return texteditor_insertfilter_next_terminate(filter, result);
324         }
325
326         filter->state = TEXTEDITOR_INSTERTFILTER_STATE_RUNNING;
327         result->data = inner_result.data;
328         result->len = inner_result.len;
329
330         return True;
331 }
332
333 LOCAL Bool texteditor_insertfilter_next_state_running(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
334 {
335         texteditor_insertfilter_innerresult inner_result;
336         Bool cont;
337
338         cont = texteditor_insertfilter_chratio(filter, &inner_result);
339         if (cont == False) {
340                 return texteditor_insertfilter_next_terminate(filter, result);
341         }
342
343         filter->state = TEXTEDITOR_INSTERTFILTER_STATE_RUNNING;
344         result->data = inner_result.data;
345         result->len = inner_result.len;
346
347         return True;
348 }
349
350 LOCAL Bool texteditor_insertfilter_next_state_last_langcode(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
351 {
352         Bool ok;
353
354         ok = tadlangcodecmp(&filter->first.lang, &filter->current.lang);
355         if (ok == False) {
356                 filter->state = TEXTEDITOR_INSTERTFILTER_STATE_LAST;
357                 texteditor_insertfilter_setresult_firstlangcode(filter, result);
358                 return True;
359         }
360
361         return False;
362 }
363
364 LOCAL Bool texteditor_insertfilter_next_state_last(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
365 {
366         return False;
367 }
368
369 EXPORT Bool texteditor_insertfilter_next(texteditor_insertfilter_t *filter, texteditor_insertfilter_result *result)
370 {
371         Bool cont = False;
372
373         switch (filter->state) {
374         case TEXTEDITOR_INSTERTFILTER_STATE_START:
375                 DP_STATE("STATE_START");
376                 cont = texteditor_insertfilter_next_state_start(filter, result);
377                 break;
378         case TEXTEDITOR_INSTERTFILTER_STATE_FIRST_LANGCODE:
379                 DP_STATE("STATE_FIRST_LANGCODE");
380                 cont = texteditor_insertfilter_next_state_langcode(filter, result);
381                 break;
382         case TEXTEDITOR_INSTERTFILTER_STATE_RUNNING:
383                 DP_STATE("STATE_RUNNING");
384                 cont = texteditor_insertfilter_next_state_running(filter, result);
385                 break;
386         case TEXTEDITOR_INSTERTFILTER_STATE_LAST_LANGCODE:
387                 DP_STATE("STATE_LAST_LANGCODE");
388                 cont = texteditor_insertfilter_next_state_last_langcode(filter, result);
389                 break;
390         case TEXTEDITOR_INSTERTFILTER_STATE_LAST:
391                 DP_STATE("STATE_LAST");
392                 cont = texteditor_insertfilter_next_state_last(filter, result);
393                 break;
394         }
395
396         return cont;
397 }
398
399 EXPORT VOID texteditor_insertfilter_initialize(texteditor_insertfilter_t *filter, tadlangcode *lang, RATIO w_ratio, UB *data, W len)
400 {
401         filter->state = TEXTEDITOR_INSTERTFILTER_STATE_START;
402         filter->first.lang = *lang;
403         filter->first.w_ratio = w_ratio;
404         filter->current.lang = (tadlangcode){0, 0x21};
405         filter->current.w_ratio = 0x0101;
406         tadstack_initialize(&filter->tadstack);
407         taditerator_initialize(&filter->iterator, (TC*)data, len / sizeof(TC));
408 }
409
410 EXPORT VOID texteditor_insertfilter_finalize(texteditor_insertfilter_t *filter)
411 {
412         taditerator_finalize(&filter->iterator);
413         tadstack_finalize(&filter->tadstack);
414 }