OSDN Git Service

change stackfilter api.
[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 #include        <bassert.h>
31
32 #include        <tad/taditerator.h>
33 #include        <tad/tadstack.h>
34
35 #include        "texteditor_stackfilter.h"
36
37 #ifdef BCHAN_CONFIG_DEBUG
38 # define DP(arg) printf arg
39 # define DP_ER(msg, err) printf("%s (%d/%x)\n", msg, err>>16, err)
40 #else
41 # define DP(arg) /**/
42 # define DP_ER(msg, err) /**/
43 #endif
44
45 #if 0
46 #define DP_STATE(s) printf("%s\n", s)
47 #else
48 #define DP_STATE(s) /**/
49 #endif
50
51 /* */
52
53 LOCAL Bool texteditor_insertfilter_w_ratio_isZenkaku(RATIO w_ratio)
54 {
55         UB a,b;
56
57         a = w_ratio >> 8;
58         b = w_ratio & 0xFF;
59
60         if (b == 0) {
61                 return True;
62         }
63         if (a == b) {
64                 return True;
65         }
66         return False;
67 }
68
69 LOCAL Bool texteditor_insertfilter_w_ratio_isSystemScript(tadlangcode *lang)
70 {
71         return tadlangcodecmpTC((TC[]){0xFE21}, 1, lang);
72 }
73
74 /* */
75
76 LOCAL TC textediter_insertfilter_zenkakufusen[] = { 0xFFA2, 0x0006, 0x0300, 0x0101, 0x0101 };
77 LOCAL TC textediter_insertfilter_hankakufusen[] = { 0xFFA2, 0x0006, 0x0300, 0x0101, 0x0102 };
78 #define TEXTEDITOR_INSERTFILTER_FUSEN_LENGTH 5
79
80 LOCAL VOID texteditor_insertfilter_pushback_segment(texteditor_insertfilter_t *filter, tadsegment *segment)
81 {
82         assert(filter->result_buffer.used < TEXTEDITOR_INSERTFILTER_RESULT_BUFFER_LEN);
83         filter->result_buffer.segs[filter->result_buffer.used] = *segment;
84         filter->result_buffer.used++;
85 }
86
87 LOCAL VOID texteditor_insertfilter_pushback_zenkakufusen(texteditor_insertfilter_t *filter)
88 {
89         tadsegment segment;
90         segment.type = TADSEGMENT_TYPE_VARIABLE;
91         segment.value.variable.raw = (UB*)textediter_insertfilter_zenkakufusen;
92         segment.value.variable.rawlen = TEXTEDITOR_INSERTFILTER_FUSEN_LENGTH * sizeof(TC);
93         texteditor_insertfilter_pushback_segment(filter, &segment);
94 }
95
96 LOCAL VOID texteditor_insertfilter_pushback_hankakufusen(texteditor_insertfilter_t *filter)
97 {
98         tadsegment segment;
99         segment.type = TADSEGMENT_TYPE_VARIABLE;
100         segment.value.variable.raw = (UB*)textediter_insertfilter_hankakufusen;
101         segment.value.variable.rawlen = TEXTEDITOR_INSERTFILTER_FUSEN_LENGTH * sizeof(TC);
102         texteditor_insertfilter_pushback_segment(filter, &segment);
103 }
104
105 LOCAL VOID texteditor_insertfilter_pushback_systemlangcode(texteditor_insertfilter_t *filter)
106 {
107         tadsegment segment;
108         segment.type = TADSEGMENT_TYPE_LANGCODE;
109         segment.value.lang = (tadlangcode){0, 0x21};
110         texteditor_insertfilter_pushback_segment(filter, &segment);
111 }
112
113 LOCAL VOID texteditor_insertfilter_pushback_firstlangcode(texteditor_insertfilter_t *filter)
114 {
115         tadsegment segment;
116         segment.type = TADSEGMENT_TYPE_LANGCODE;
117         segment.value.lang = filter->first.lang;
118         texteditor_insertfilter_pushback_segment(filter, &segment);
119 }
120
121 LOCAL W texteditor_insertfilter_put_filtering(texteditor_insertfilter_t *filter, tadsegment *segment)
122 {
123         W ret;
124         Bool cont;
125         tadsegment *result;
126         UB segid, subid, *segdata;
127         UW seglen;
128         texteditor_stackfilterresult_t *stack_result;
129
130         ret = texteditor_stackfilter_put(&filter->stack, segment, &stack_result);
131         if (ret == TEXTEDITOR_STACKFILTER_PUT_RESULT_FORMAT_ERROR) {
132                 return TEXTEDITOR_INSERTFILTER_PUT_RESULT_FORMAT_ERROR;
133         }
134         for(;;) {
135                 cont = texteditor_stackfilterresult_next(stack_result, &result);
136                 if (cont == False) {
137                         break;
138                 }
139
140                 if (result->type == TADSEGMENT_TYPE_VARIABLE) {
141                         tadsegment_getvariable(result, &segid, &seglen, &segdata);
142                         if (segid != TS_TFONT) {
143                                 continue;
144                         }
145                         if (seglen < 6) {
146                                 continue;
147                         }
148                         subid = *(UH*)segdata >> 8;
149                         if (subid != 3) {
150                                 continue;
151                         }
152
153                         filter->current.w_ratio = *((UH*)segdata + 5);
154                 } else if (result->type == TADSEGMENT_TYPE_LANGCODE) {
155                         filter->current.lang = result->value.lang;
156                 }
157
158                 texteditor_insertfilter_pushback_segment(filter, result);
159         }
160
161         return TEXTEDITOR_INSERTFILTER_PUT_RESULT_OK;
162 }
163
164 LOCAL W texteditor_insertfilter_put_state_start(texteditor_insertfilter_t *filter, tadsegment *segment, texteditor_insertfilterresult_t **result)
165 {
166         Bool ok;
167
168         ok = texteditor_insertfilter_w_ratio_isZenkaku(filter->first.w_ratio);
169         if (ok == False) {
170                 texteditor_insertfilter_pushback_zenkakufusen(filter);
171         }
172         ok = texteditor_insertfilter_w_ratio_isSystemScript(&filter->first.lang);
173         if (ok == False) {
174                 texteditor_insertfilter_pushback_systemlangcode(filter);
175         }
176
177         *result = &filter->result;
178
179         filter->state = TEXTEDITOR_INSERTFILTER_STATE_RUNNING;
180
181         return texteditor_insertfilter_put_filtering(filter, segment);
182 }
183
184 LOCAL W texteditor_insertfilter_put_state_running(texteditor_insertfilter_t *filter, tadsegment *segment, texteditor_insertfilterresult_t **result)
185 {
186         filter->result_buffer.used = 0;
187         filter->result_buffer.consumed = 0;
188
189         *result = &filter->result;
190
191         return texteditor_insertfilter_put_filtering(filter, segment);
192 }
193
194 EXPORT W texteditor_insertfilter_put(texteditor_insertfilter_t *filter, tadsegment *segment, texteditor_insertfilterresult_t **result)
195 {
196         switch (filter->state) {
197         case TEXTEDITOR_INSERTFILTER_STATE_START:
198                 DP_STATE("put:STATE_START");
199                 return texteditor_insertfilter_put_state_start(filter, segment, result);
200         case TEXTEDITOR_INSERTFILTER_STATE_RUNNING:
201                 DP_STATE("put:STATE_RUNNING");
202                 return texteditor_insertfilter_put_state_running(filter, segment, result);
203         case TEXTEDITOR_INSERTFILTER_STATE_END:
204                 DP_STATE("put:STATE_END");
205                 return TEXTEDITOR_INSERTFILTER_PUT_RESULT_FORMAT_ERROR;
206         }
207         return TEXTEDITOR_INSERTFILTER_PUT_RESULT_FORMAT_ERROR;
208 }
209
210 EXPORT VOID texteditor_insertfilter_endinput(texteditor_insertfilter_t *filter, texteditor_insertfilterresult_t **result)
211 {
212         Bool ok, zen;
213
214         filter->result_buffer.used = 0;
215         filter->result_buffer.consumed = 0;
216         *result = &filter->result;
217
218         switch (filter->state) {
219         case TEXTEDITOR_INSERTFILTER_STATE_START:
220                 DP_STATE("end:STATE_START");
221                 break;
222         case TEXTEDITOR_INSERTFILTER_STATE_RUNNING:
223                 DP_STATE("end:STATE_RUNNING");
224                 if (filter->first.w_ratio != filter->current.w_ratio) {
225                         zen = texteditor_insertfilter_w_ratio_isZenkaku(filter->first.w_ratio);
226                         if (zen == False) {
227                                 texteditor_insertfilter_pushback_hankakufusen(filter);
228                         } else {
229                                 texteditor_insertfilter_pushback_zenkakufusen(filter);
230                         }
231                 }
232                 ok = tadlangcodecmp(&filter->first.lang, &filter->current.lang);
233                 if (ok == False) {
234                         texteditor_insertfilter_pushback_firstlangcode(filter);
235                 }
236                 break;
237         case TEXTEDITOR_INSERTFILTER_STATE_END:
238                 DP_STATE("end:STATE_END");
239                 break;
240         }
241 }
242
243 EXPORT Bool texteditor_insertfilterresult_next(texteditor_insertfilterresult_t *result, tadsegment **segment)
244 {
245         texteditor_insertfilter_t *filter = result->filter;
246
247         if (filter->result_buffer.consumed >= filter->result_buffer.used) {
248                 return False;
249         }
250
251         *segment = filter->result_buffer.segs + filter->result_buffer.consumed;
252         filter->result_buffer.consumed++;
253
254         if (filter->result_buffer.consumed >= filter->result_buffer.used) {
255                 filter->result_buffer.used = 0;
256                 filter->result_buffer.consumed = 0;
257         }
258
259         return True;
260 }
261
262 EXPORT VOID texteditor_insertfilter_initialize(texteditor_insertfilter_t *filter, tadlangcode *lang, RATIO w_ratio)
263 {
264         texteditor_stackfilter_initialize(&filter->stack);
265         filter->state = TEXTEDITOR_INSERTFILTER_STATE_START;
266         filter->first.lang = *lang;
267         filter->first.w_ratio = w_ratio;
268         filter->current.lang = (tadlangcode){0, 0x21};
269         filter->current.w_ratio = 0x0101;
270         filter->result_buffer.used = 0;
271         filter->result_buffer.consumed = 0;
272         filter->result.filter = filter;
273 }
274
275 EXPORT VOID texteditor_insertfilter_finalize(texteditor_insertfilter_t *filter)
276 {
277         texteditor_stackfilter_finalize(&filter->stack);
278 }