1 #include "sdlskk_internal.h"
2 #include <ctype.h>
3 #include <assert.h>
4 
5 #define INPUT_BUF_SIZE 2048
6 #define HENKAN_BUF_SIZE 512
7 #define OKURIGANA_BUF_SIZE 10
8 #define PREFIX_BUF_SIZE 10
9 
10 #define START_MINIBUFFER_WORDSELECT 4
11 #define MINIBUFFER_WORDSELECT_MAX_WORDS 7
12 
SDLSKK_Context_new(SDLSKK_Dictionary * dict,SDLSKK_RomKanaRuleTable * table,SDLSKK_Keybind * keybind,int use_minibuffer)13 SDLSKK_Context* SDLSKK_Context_new( SDLSKK_Dictionary* dict,
14 				    SDLSKK_RomKanaRuleTable* table,
15 				    SDLSKK_Keybind* keybind,
16 				    int use_minibuffer )
17 {
18   SDLSKK_Context* context = SDLSKK_malloc( sizeof(SDLSKK_Context) );
19 
20   context->dict = dict;
21   context->rule_table = table;
22   context->mode = SDLSKK_J_KAKUTEI_MODE;
23   context->old_mode = SDLSKK_J_KAKUTEI_MODE;
24   context->str = SDLSKK_XStr_new4( "", INPUT_BUF_SIZE );
25   context->prefix = SDLSKK_XStr_new4( "", PREFIX_BUF_SIZE );
26   context->henkan_key = SDLSKK_XStr_new4 ( "", HENKAN_BUF_SIZE );
27   context->henkan_okurigana = SDLSKK_XStr_new4( "", OKURIGANA_BUF_SIZE );
28   context->dict_item = NULL;
29   context->display_str = SDLSKK_XStr_new4( "", INPUT_BUF_SIZE );
30   context->minibuffer_str = SDLSKK_XStr_new4( "", INPUT_BUF_SIZE );
31   context->cursor_pos = 0;
32   context->henkan_buf_pos = 0;
33   context->katakana_on = 0;
34   context->use_minibuffer = use_minibuffer;
35   context->child_context = NULL;
36   context->parent_context = NULL;
37   context->cut_buffer = SDLSKK_XStr_new4( "", INPUT_BUF_SIZE );
38   context->marked_point = NOT_MARKED;
39   context->keybind = keybind;
40   return context;
41 }
42 
SDLSKK_Context_delete(SDLSKK_Context * context)43 void SDLSKK_Context_delete( SDLSKK_Context* context )
44 {
45   if( context == NULL )
46     return;
47   SDLSKK_XStr_delete( context->str );
48   SDLSKK_XStr_delete( context->prefix );
49   SDLSKK_XStr_delete( context->henkan_key );
50   SDLSKK_XStr_delete( context->henkan_okurigana );
51   SDLSKK_XStr_delete( context->display_str );
52   SDLSKK_XStr_delete( context->minibuffer_str );
53   SDLSKK_DictItem_delete( context->dict_item );
54   SDLSKK_Context_delete( context->child_context );
55   SDLSKK_XStr_delete( context->cut_buffer );
56   free( context );
57 }
58 
SDLSKK_Context_insert_Char(SDLSKK_Context * context,SDLSKK_Char c)59 void SDLSKK_Context_insert_Char( SDLSKK_Context* context, SDLSKK_Char c )
60 {
61   SDLSKK_XStr_insert_Char( context->str, context->cursor_pos, c);
62   ++(context->cursor_pos);
63 }
64 
Context_insert_XStr(SDLSKK_Context * context,SDLSKK_XStr * str)65 static void Context_insert_XStr( SDLSKK_Context* context, SDLSKK_XStr* str )
66 {
67   SDLSKK_XStr_insert_Str( context->str, context->cursor_pos, str->buf);
68   context->cursor_pos += str->len;
69 }
70 
SDLSKK_Context_insert_Str(SDLSKK_Context * context,SDLSKK_Char * str)71 void SDLSKK_Context_insert_Str( SDLSKK_Context* context, SDLSKK_Char *str )
72 {
73   SDLSKK_XStr_insert_Str( context->str, context->cursor_pos, str );
74   context->cursor_pos += SDLSKK_Str_len( str );
75 }
76 
SDLSKK_XStr_chop(SDLSKK_XStr * str)77 static void SDLSKK_XStr_chop( SDLSKK_XStr* str )
78 {
79   SDLSKK_XStr_delete_Char( str, str->len - 1 );
80 }
81 
Context_henkan_kakutei(SDLSKK_Context * context)82 static void Context_henkan_kakutei( SDLSKK_Context* context )
83 {
84   SDLSKK_Context_insert_Str( context,
85 			     SDLSKK_DictItem_get_current( context->dict_item ) );
86   SDLSKK_Context_insert_Str( context, context->henkan_okurigana->buf );
87   SDLSKK_DictItem_commit( context->dict_item );
88   SDLSKK_DictItem_delete( context->dict_item );
89   SDLSKK_XStr_clear( context->henkan_okurigana );
90   context->dict_item = NULL;
91   context->mode = SDLSKK_J_KAKUTEI_MODE;
92 
93 }
94 
Context_unset_mark(SDLSKK_Context * context)95 static void Context_unset_mark( SDLSKK_Context* context )
96 {
97   context->marked_point = NOT_MARKED;
98 }
99 
convert_hiragana_katakana(SDLSKK_Char * str,int katanana)100 static SDLSKK_Char* convert_hiragana_katakana( SDLSKK_Char* str, int katanana )
101 {
102   if( katanana )
103     return SDLSKK_Str_hiragana_to_katakana( str );
104   else
105     return SDLSKK_Str_katakana_to_hiragana( str );
106 }
107 
get_kana(SDLSKK_RomKanaElement * kana,int katakana_on)108 static SDLSKK_Char* get_kana( SDLSKK_RomKanaElement* kana, int katakana_on )
109 {
110   return katakana_on?kana->katakana:kana->hiragana;
111 }
112 
resolve_romkana(SDLSKK_RomKanaRuleTable * table,SDLSKK_XStr * prefix,SDLSKK_XStr * inserted_str,int * pos,int katakana_on)113 static void resolve_romkana( SDLSKK_RomKanaRuleTable* table,
114 			     SDLSKK_XStr* prefix, SDLSKK_XStr* inserted_str,
115 			     int* pos, int katakana_on )
116 {
117   SDLSKK_RomKanaElement* kana;
118   SDLSKK_XStr* prefix_buf;
119 
120   if( prefix->len == 0 )
121     return;
122 
123   switch( SDLSKK_RomKanaRuleTable_get( table, prefix->buf, &kana ) ){
124 
125   case SDLSKK_RomKana_NoCandidate:
126     prefix_buf = SDLSKK_XStr_new5( prefix );
127     SDLSKK_XStr_chop( prefix_buf );
128 
129     if( SDLSKK_RomKanaRuleTable_get( table, prefix_buf->buf, &kana ) ==
130 	SDLSKK_RomKana_UnresolvedCandidate ){
131       SDLSKK_Char rest;
132       SDLSKK_XStr_insert_Str( inserted_str, *pos,
133 			      get_kana( kana, katakana_on ) );
134       *pos += SDLSKK_Str_len( get_kana( kana, katakana_on ) );
135 
136 
137       rest = prefix->buf[prefix->len-1];
138       SDLSKK_XStr_clear( prefix );
139       SDLSKK_XStr_insert_Char( prefix, 0, rest );
140 
141       resolve_romkana( table, prefix, inserted_str, pos, katakana_on );
142     }else{
143       SDLSKK_XStr_delete_Char( prefix, 0 );
144       resolve_romkana( table, prefix, inserted_str, pos, katakana_on );
145     }
146     SDLSKK_XStr_delete( prefix_buf );
147     return;
148 
149   case SDLSKK_RomKana_SomeCandidates:
150     return;
151 
152   case SDLSKK_RomKana_OneCandidate:
153     SDLSKK_XStr_insert_Str( inserted_str, *pos, get_kana( kana, katakana_on ));
154     *pos += SDLSKK_Str_len( get_kana( kana, katakana_on ) );
155 
156     SDLSKK_XStr_copy_Str( prefix, kana->next_state );
157     return;
158 
159   case SDLSKK_RomKana_UnresolvedCandidate:
160     return;
161   }
162 }
163 
resolve_finish(SDLSKK_RomKanaRuleTable * rule_table,SDLSKK_XStr * prefix,SDLSKK_XStr * inserted_str,int * pos)164 static void resolve_finish( SDLSKK_RomKanaRuleTable* rule_table,
165 			    SDLSKK_XStr* prefix,
166 			    SDLSKK_XStr* inserted_str,
167 			    int* pos )
168 {
169   SDLSKK_RomKanaElement* candidate;
170   if( SDLSKK_RomKanaRuleTable_get( rule_table, prefix->buf, &candidate ) ==
171       SDLSKK_RomKana_UnresolvedCandidate ){
172     SDLSKK_XStr_insert_Str( inserted_str, *pos, candidate->hiragana );
173     *pos += SDLSKK_Str_len( candidate->hiragana );
174     SDLSKK_XStr_clear( prefix );
175   }else{
176     SDLSKK_XStr_clear( prefix );
177   }
178 }
179 
Context_is_in_word_register_mode(SDLSKK_Context * context)180 static int Context_is_in_word_register_mode( SDLSKK_Context* context )
181 {
182   return ( context->parent_context != NULL );
183 }
184 
Context_is_in_minibuffer_wordselect_mode(SDLSKK_Context * context)185 static int Context_is_in_minibuffer_wordselect_mode( SDLSKK_Context* context )
186 {
187   if( context->dict_item == NULL )
188     return 0;
189   if( ! context->use_minibuffer )
190     return 0;
191   return ( SDLSKK_DictItem_get_count( context->dict_item ) >=
192 	   START_MINIBUFFER_WORDSELECT ) ;
193 }
194 
normal_on_j_kakutei_mode(SDLSKK_Context * context,char key)195 static void normal_on_j_kakutei_mode( SDLSKK_Context* context, char key )
196 {
197   Context_unset_mark( context );
198   SDLSKK_XStr_insert_Char( context->prefix, context->prefix->len , key );
199   resolve_romkana( context->rule_table, context->prefix, context->str,
200 		   &context->cursor_pos, context->katakana_on  );
201 }
upper_on_j_kakutei_mode(SDLSKK_Context * context,char key)202 static void upper_on_j_kakutei_mode( SDLSKK_Context* context, char key )
203 {
204   Context_unset_mark( context );
205   SDLSKK_XStr_clear( context->prefix );
206   SDLSKK_XStr_clear( context->henkan_key );
207   SDLSKK_XStr_clear( context->henkan_okurigana );
208   context->henkan_buf_pos = 0;
209   context->mode = SDLSKK_J_HENKAN_ON_MODE;
210 
211   SDLSKK_XStr_insert_Char( context->prefix, context->prefix->len,
212 			   tolower( key ) );
213   resolve_romkana( context->rule_table, context->prefix,
214 		   context->henkan_key, &(context->henkan_buf_pos),
215 		   0 );
216 }
217 
graph_on_latin_mode(SDLSKK_Context * context,char key)218 static void graph_on_latin_mode( SDLSKK_Context* context, char key )
219 {
220   Context_unset_mark( context );
221   SDLSKK_Context_insert_Char( context, key );
222 }
change_to_latin_mode_on_j_kakutei_mode(SDLSKK_Context * context,char key)223 static void change_to_latin_mode_on_j_kakutei_mode( SDLSKK_Context* context, char key )
224 {
225   context->mode = SDLSKK_LATIN_MODE;
226   SDLSKK_XStr_clear( context->prefix );
227   return;
228 }
change_to_jisx0208_latin_mode_on_j_kakutei_mode(SDLSKK_Context * context,char key)229 static void change_to_jisx0208_latin_mode_on_j_kakutei_mode( SDLSKK_Context* context, char key )
230 {
231   context->mode = SDLSKK_JISX0208_LATIN_MODE;
232   SDLSKK_XStr_clear( context->prefix );
233   return;
234 }
235 
change_to_abbrev_mode_on_j_kakutei_mode(SDLSKK_Context * context,char key)236 static void change_to_abbrev_mode_on_j_kakutei_mode( SDLSKK_Context* context, char key )
237 {
238   Context_unset_mark( context );
239   context->mode = SDLSKK_ABBREV_MODE;
240   SDLSKK_XStr_clear( context->prefix );
241   SDLSKK_XStr_clear( context->henkan_key );
242   context->henkan_buf_pos = 0;
243   return;
244 }
245 
graph_on_j_henkan_okuri_mode(SDLSKK_Context * context,char key)246 static void graph_on_j_henkan_okuri_mode( SDLSKK_Context* context, char key )
247 {
248   int pos;
249 
250   key = tolower(key);
251 
252   SDLSKK_XStr_insert_Char( context->prefix, context->prefix->len, key );
253   pos = context->henkan_okurigana->len;
254   resolve_romkana( context->rule_table, context->prefix,
255 		   context->henkan_okurigana, &pos, 0 );
256   if( context->prefix->len == 0 ){
257     SDLSKK_XStr_insert_Char( context->henkan_key, context->henkan_key->len,
258 			     context->okuri_char );
259     context->dict_item = SDLSKK_Dict_get( context->dict,
260 					  context->henkan_key->buf );
261     SDLSKK_XStr_chop( context->henkan_key );
262     if( context->dict_item == NULL ){
263       context->mode = SDLSKK_J_HENKAN_ON_MODE;
264       SDLSKK_XStr_clear( context->henkan_okurigana );
265       return;
266     }else{
267       context->old_mode = SDLSKK_J_HENKAN_ON_MODE;
268       context->mode = SDLSKK_J_HENKAN_ACTIVE_MODE;
269       return;
270     }
271   }
272 }
273 
normal_on_j_henkan_on_mode(SDLSKK_Context * context,char key)274 static void normal_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
275 {
276   SDLSKK_XStr_insert_Char( context->prefix, context->prefix->len, key );
277   resolve_romkana( context->rule_table, context->prefix,
278 		   context->henkan_key, &(context->henkan_buf_pos),
279 		   0 );
280 }
281 
upper_on_j_henkan_on_mode(SDLSKK_Context * context,char key)282 static void upper_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
283 {
284   if( context->henkan_key->len == 0 ){
285     normal_on_j_henkan_on_mode( context, tolower(key) );
286     return;
287   }
288   if( context->prefix->len != 0 ){
289     normal_on_j_henkan_on_mode( context, tolower(key) );
290     if( context->prefix->len == 0 ){
291       return;
292     }else{
293       context->okuri_char = tolower( key );
294       SDLSKK_XStr_clear( context->henkan_okurigana );
295       context->mode = SDLSKK_J_HENKAN_OKURI_MODE;
296       return;
297     }
298   }
299   context->okuri_char = tolower( key );
300   SDLSKK_XStr_clear( context->henkan_okurigana );
301   context->mode = SDLSKK_J_HENKAN_OKURI_MODE;
302   SDLSKK_Context_input_key( context, tolower( key ) );
303 }
304 
change_to_latin_mode_on_j_henkan_on_mode(SDLSKK_Context * context,char key)305 static void change_to_latin_mode_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
306 {
307   SDLSKK_XStr_clear( context->prefix );
308   Context_insert_XStr( context, context->henkan_key );
309   SDLSKK_XStr_clear( context->henkan_key );
310   context->mode = SDLSKK_LATIN_MODE;
311 }
change_to_jisx0208_latin_mode_on_j_henkan_on_mode(SDLSKK_Context * context,char key)312 static void change_to_jisx0208_latin_mode_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
313 {
314   SDLSKK_XStr_clear( context->prefix );
315   Context_insert_XStr( context, context->henkan_key );
316   SDLSKK_XStr_clear( context->henkan_key );
317   context->mode = SDLSKK_JISX0208_LATIN_MODE;
318 }
319 
graph_on_j_henkan_on_mode(SDLSKK_Context * context,char key)320 static void graph_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
321 {
322   if( islower(key) ){
323     normal_on_j_henkan_on_mode( context, key );
324   }
325   if( isupper(key) ){
326     upper_on_j_henkan_on_mode( context, key );
327   }
328 }
329 
graph_on_j_henkan_active_mode(SDLSKK_Context * context,char key)330 static void graph_on_j_henkan_active_mode( SDLSKK_Context* context, char key )
331 {
332   /*
333     generated by
334      ruby -e ' a = Array.new(256,-1); a[?a]=0; a[?s]=1; a[?d]=2; a[?f]=3; \
335      a[?j]=4; a[?k]=5; a[?l]=6 ; p a' > ary
336   */
337   int i;
338   SDLSKK_DictionaryItem item;
339   static const int cnt[] = {
340     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 2, -1, 3, -1, -1, -1, 4, 5, 6, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
341   };
342 
343   if( Context_is_in_minibuffer_wordselect_mode( context ) ){
344     if( cnt[key]==-1 )
345       return;
346     item = *(context->dict_item);
347     for( i=0; i < cnt[key]; ++i ){
348       if( SDLSKK_DictItem_is_end( &item ) )
349 	return;
350       SDLSKK_DictItem_next( &item );
351     }
352     *(context->dict_item) = item;
353     Context_henkan_kakutei( context );
354     return;
355   }
356   Context_henkan_kakutei( context );
357   SDLSKK_Context_input_key( context, key );
358 }
359 
graph_on_abbrev_mode(SDLSKK_Context * context,char key)360 static void graph_on_abbrev_mode( SDLSKK_Context* context, char key )
361 {
362   SDLSKK_XStr_insert_Char( context->henkan_key, context->henkan_buf_pos, key );
363   ++(context->henkan_buf_pos);
364 }
365 
graph_on_jisx0208_latin_mode(SDLSKK_Context * context,char key)366 static void graph_on_jisx0208_latin_mode( SDLSKK_Context* context, char key )
367 {
368   Context_unset_mark( context );
369   SDLSKK_Context_insert_Char( context, SDLSKK_latin_to_jisx0208_Char( key ) );
370 }
371 
toggle_katakana_on_j_kakutei_mode(SDLSKK_Context * context,char key)372 static void toggle_katakana_on_j_kakutei_mode( SDLSKK_Context* context, char key )
373 {
374   SDLSKK_XStr_clear( context->prefix );
375   context->katakana_on = !context->katakana_on;
376 }
377 
toggle_kata_on_j_henkan_on_mode(SDLSKK_Context * context,char key)378 static void toggle_kata_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
379 {
380   SDLSKK_Char* str;
381 
382   resolve_finish( context->rule_table, context->prefix, context->henkan_key,
383 		  &context->henkan_buf_pos );
384   str = convert_hiragana_katakana( context->henkan_key->buf,
385 				   ! context->katakana_on );
386   SDLSKK_Context_insert_Str( context, str );
387   free( str );
388   SDLSKK_XStr_clear( context->henkan_key );
389   context->mode = SDLSKK_J_KAKUTEI_MODE;
390 }
391 
space_on_latin_mode(SDLSKK_Context * context,char key)392 static void space_on_latin_mode( SDLSKK_Context* context, char key )
393 {
394   SDLSKK_Context_insert_Char( context, ' ' );
395 }
space_on_j_kakutei_mode(SDLSKK_Context * context,char key)396 static void space_on_j_kakutei_mode( SDLSKK_Context* context, char key )
397 {
398   Context_unset_mark( context );
399   SDLSKK_XStr_clear( context->prefix );
400   SDLSKK_Context_insert_Char( context, ' ' );
401 }
402 
403 
change_to_word_register_mode(SDLSKK_Context * context)404 static void change_to_word_register_mode( SDLSKK_Context* context )
405 {
406   context->child_context = SDLSKK_Context_new( context->dict,
407 					       context->rule_table,
408 					       context->keybind,
409 					       0 );
410   context->child_context->parent_context = context;
411 }
space_on_j_henkan_on_mode(SDLSKK_Context * context,char key)412 static void space_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
413 {
414   resolve_finish( context->rule_table, context->prefix,
415 		  context->henkan_key, &context->henkan_buf_pos );
416 
417   context->old_mode = SDLSKK_J_HENKAN_ON_MODE;
418   context->dict_item = SDLSKK_Dict_get( context->dict, context->henkan_key->buf );
419   if( context->dict_item == NULL ){
420     change_to_word_register_mode( context );
421   }else{
422     context->mode = SDLSKK_J_HENKAN_ACTIVE_MODE;
423   }
424 }
space_on_j_henkan_active_mode(SDLSKK_Context * context,char key)425 static void space_on_j_henkan_active_mode( SDLSKK_Context* context, char key )
426 {
427   int i;
428 
429   if( Context_is_in_minibuffer_wordselect_mode( context ) ){
430     for( i=0; i < MINIBUFFER_WORDSELECT_MAX_WORDS; ++i ){
431       if( SDLSKK_DictItem_is_end( context->dict_item ) ){
432 	change_to_word_register_mode( context );
433 	return;
434       }
435       SDLSKK_DictItem_next( context->dict_item );
436     }
437     return;
438   }
439   if( SDLSKK_DictItem_is_end( context->dict_item ) ){
440     change_to_word_register_mode( context );
441     return;
442   }
443   SDLSKK_DictItem_next( context->dict_item );
444 }
space_on_abbrev_mode(SDLSKK_Context * context,char key)445 static void space_on_abbrev_mode( SDLSKK_Context* context, char key )
446 {
447   context->old_mode = SDLSKK_ABBREV_MODE;
448   context->dict_item = SDLSKK_Dict_get( context->dict, context->henkan_key->buf );
449   if( context->dict_item == NULL ){
450     change_to_word_register_mode( context );
451   }else{
452     context->mode = SDLSKK_J_HENKAN_ACTIVE_MODE;
453   }
454 }
455 
kakutei_on_latin_mode(SDLSKK_Context * context,char key)456 static void kakutei_on_latin_mode( SDLSKK_Context* context, char key )
457 {
458   context->mode = SDLSKK_J_KAKUTEI_MODE;
459 }
460 
kakutei_on_j_henkan_on_mode(SDLSKK_Context * context,char key)461 static void kakutei_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
462 {
463   SDLSKK_Char* kana;
464 
465   SDLSKK_XStr_clear( context->prefix );
466   kana = convert_hiragana_katakana( context->henkan_key->buf,
467 				    context->katakana_on );
468   SDLSKK_Context_insert_Str( context, kana );
469   free( kana );
470   SDLSKK_XStr_clear( context->henkan_key );
471   context->mode = SDLSKK_J_KAKUTEI_MODE;
472   return;
473 }
kakutei_on_j_henkan_active_mode(SDLSKK_Context * context,char key)474 static void kakutei_on_j_henkan_active_mode( SDLSKK_Context* context, char key )
475 {
476   if(  Context_is_in_minibuffer_wordselect_mode( context ) )
477     return;
478   Context_henkan_kakutei( context );
479 }
480 
kakutei_on_abbrev_mode(SDLSKK_Context * context,char key)481 static void kakutei_on_abbrev_mode( SDLSKK_Context* context, char key )
482 {
483   SDLSKK_Context_insert_Str( context, context->henkan_key->buf );
484   SDLSKK_XStr_clear( context->henkan_key );
485   context->mode = SDLSKK_J_KAKUTEI_MODE;
486 }
487 
kouho_backward_on_j_henkan_active_mode(SDLSKK_Context * context,char key)488 static void kouho_backward_on_j_henkan_active_mode( SDLSKK_Context* context, char key )
489 {
490   int i;
491 
492   if( Context_is_in_minibuffer_wordselect_mode( context )
493       && ( SDLSKK_DictItem_get_count( context->dict_item )
494 	   != START_MINIBUFFER_WORDSELECT ) ){
495     for( i=0; i < MINIBUFFER_WORDSELECT_MAX_WORDS; i++ )
496       SDLSKK_DictItem_prev( context->dict_item );
497     return;
498   }
499 
500   SDLSKK_DictItem_prev( context->dict_item );
501 }
forward_on_latin_mode(SDLSKK_Context * context,char key)502 static void forward_on_latin_mode( SDLSKK_Context* context, char key )
503 {
504   if( context->cursor_pos < context->str->len )
505     ++(context->cursor_pos);
506   return;
507 }
forward_on_j_kakutei_mode(SDLSKK_Context * context,char key)508 static void forward_on_j_kakutei_mode( SDLSKK_Context* context, char key )
509 {
510   if( context->prefix->len > 0 ){
511     SDLSKK_XStr_clear( context->prefix );
512   }
513   if( context->cursor_pos < context->str->len )
514     ++(context->cursor_pos);
515   return;
516 }
517 
518 
backward_on_latin_mode(SDLSKK_Context * context,char key)519 static void backward_on_latin_mode( SDLSKK_Context* context, char key )
520 {
521   if( context->cursor_pos > 0 )
522     --(context->cursor_pos);
523   return;
524 }
backward_on_j_kakutei_mode(SDLSKK_Context * context,char key)525 static void backward_on_j_kakutei_mode( SDLSKK_Context* context, char key )
526 {
527   if( context->prefix->len > 0 ){
528     SDLSKK_XStr_clear( context->prefix );
529   }else if( context->cursor_pos > 0 ){
530     --(context->cursor_pos);
531   }
532   return;
533 }
534 
535 
XStr_backspace(SDLSKK_XStr * str,int * pos)536 static void XStr_backspace( SDLSKK_XStr* str, int* pos )
537 {
538   if( *pos <= 0 )
539     return;
540   SDLSKK_XStr_delete_Char( str, *pos - 1 );
541   --(*pos);
542   return;
543 }
backspace_on_latin_mode(SDLSKK_Context * context,char key)544 static void backspace_on_latin_mode( SDLSKK_Context* context, char key )
545 {
546   Context_unset_mark( context );
547   XStr_backspace( context->str, &context->cursor_pos );
548   return;
549 }
backspace_on_j_kakutei_mode(SDLSKK_Context * context,char key)550 static void backspace_on_j_kakutei_mode( SDLSKK_Context* context, char key )
551 {
552   Context_unset_mark( context );
553   if( context->prefix->len > 0 ){
554     SDLSKK_XStr_clear( context->prefix );
555   }else{
556     XStr_backspace( context->str, &context->cursor_pos );
557   }
558   return;
559 }
backspace_on_j_henkan_okuri_mode(SDLSKK_Context * context,char key)560 static void backspace_on_j_henkan_okuri_mode( SDLSKK_Context* context, char key )
561 {
562   SDLSKK_XStr_clear( context->prefix );
563   SDLSKK_XStr_clear( context->henkan_okurigana );
564   context->mode = SDLSKK_J_HENKAN_ON_MODE;
565 }
backspace_on_j_henkan_on_mode(SDLSKK_Context * context,char key)566 static void backspace_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
567 {
568   if( context->prefix->len > 0 ){
569     SDLSKK_XStr_clear( context->prefix );
570   }else if( context->henkan_key->len == 0 ){
571     context->mode = SDLSKK_J_KAKUTEI_MODE;
572   }else{
573     XStr_backspace( context->henkan_key, &context->henkan_buf_pos );
574   }
575 }
backspace_on_j_henkan_active_mode(SDLSKK_Context * context,char key)576 static void backspace_on_j_henkan_active_mode( SDLSKK_Context* context, char key )
577 {
578   if( Context_is_in_minibuffer_wordselect_mode( context ) )
579     return;
580   Context_henkan_kakutei( context );
581   backspace_on_j_kakutei_mode( context, key );
582 }
backspace_on_abbrev_mode(SDLSKK_Context * context,char key)583 static void backspace_on_abbrev_mode( SDLSKK_Context* context, char key )
584 {
585   if( context->henkan_key->len > 0 ){
586     XStr_backspace( context->henkan_key, &context->henkan_buf_pos );
587   }else{
588     context->mode = SDLSKK_J_KAKUTEI_MODE;
589   }
590 }
591 
delete_on_latin_mode(SDLSKK_Context * context,char key)592 static void delete_on_latin_mode( SDLSKK_Context* context, char key )
593 {
594   if( context->cursor_pos < context->str->len ){
595     Context_unset_mark( context );
596     context->cursor_pos += 1;
597     XStr_backspace( context->str, &context->cursor_pos );
598   }
599 }
delete_on_j_kakutei_mode(SDLSKK_Context * context,char key)600 static void delete_on_j_kakutei_mode( SDLSKK_Context* context, char key )
601 {
602   SDLSKK_XStr_clear( context->prefix );
603   delete_on_latin_mode( context, key );
604 }
605 
cancel_on_j_henkan_on_mode(SDLSKK_Context * context,char key)606 static void cancel_on_j_henkan_on_mode( SDLSKK_Context* context, char key )
607 {
608   SDLSKK_XStr_clear( context->prefix );
609   SDLSKK_XStr_clear( context->henkan_key );
610   context->mode = SDLSKK_J_KAKUTEI_MODE;
611 }
612 
cancel_on_j_henkan_okuri_mode(SDLSKK_Context * context,char key)613 static void cancel_on_j_henkan_okuri_mode( SDLSKK_Context* context, char key )
614 {
615   SDLSKK_XStr_clear( context->prefix );
616   SDLSKK_XStr_clear( context->henkan_key );
617   SDLSKK_XStr_clear( context->henkan_okurigana );
618   context->mode = SDLSKK_J_KAKUTEI_MODE;
619 }
620 
cancel_on_j_henkan_active_mode(SDLSKK_Context * context,char key)621 static void cancel_on_j_henkan_active_mode( SDLSKK_Context* context, char key )
622 {
623   SDLSKK_DictItem_delete( context->dict_item );
624   context->dict_item = NULL;
625   context->mode = context->old_mode;
626 }
627 
cancel_on_j_kakutei_mode(SDLSKK_Context * context,char key)628 static void cancel_on_j_kakutei_mode( SDLSKK_Context* context, char key )
629 {
630   SDLSKK_Context* parent_context;
631 
632   if( ! Context_is_in_word_register_mode( context ) )
633     return;
634 
635   parent_context = context->parent_context;
636   parent_context->child_context = NULL;
637   SDLSKK_Context_delete( context );
638   SDLSKK_DictItem_delete( parent_context->dict_item );
639   parent_context->dict_item = NULL;
640   parent_context->mode = parent_context->old_mode;
641 
642 }
643 
cancel_on_latin_mode(SDLSKK_Context * context,char key)644 static void cancel_on_latin_mode( SDLSKK_Context* context, char key )
645 {
646   cancel_on_j_kakutei_mode( context, key );
647 }
648 
cancel_on_abbrev_mode(SDLSKK_Context * context,char key)649 static void cancel_on_abbrev_mode( SDLSKK_Context* context, char key )
650 {
651   SDLSKK_XStr_clear( context->henkan_key );
652   context->mode = SDLSKK_J_KAKUTEI_MODE;
653 }
654 
register_word_on_j_kakutei_mode(SDLSKK_Context * context,char key)655 static void register_word_on_j_kakutei_mode( SDLSKK_Context* context, char key )
656 {
657   SDLSKK_DictionaryItem* dict_item;
658   SDLSKK_Char* henkan_key;
659 
660   if( context->parent_context == NULL )
661     return;
662 
663   if( context->str->len == 0 ){
664     cancel_on_j_kakutei_mode( context, key );
665     return;
666   }
667 
668   dict_item = context->parent_context->dict_item;
669 
670   if( dict_item == NULL ){
671     henkan_key = SDLSKK_Str_new( context->parent_context->henkan_key->buf );
672     SDLSKK_Dict_add_empty_yomi( context->parent_context->dict,
673 				henkan_key );
674     dict_item = SDLSKK_Dict_get( context->parent_context->dict,
675 				 henkan_key );
676     context->parent_context->dict_item = dict_item;
677   }
678 
679   SDLSKK_DictItem_register_word( dict_item, context->str->buf );
680 
681   SDLSKK_DictItem_set_current( dict_item, context->str->buf );
682   Context_henkan_kakutei( context->parent_context );
683 
684   context->parent_context->child_context = NULL;
685   SDLSKK_Context_delete( context );
686 
687 }
688 
yank_on_latin_mode(SDLSKK_Context * context,char key)689 static void yank_on_latin_mode( SDLSKK_Context* context, char key )
690 {
691   Context_unset_mark( context );
692   Context_insert_XStr( context, context->cut_buffer );
693 }
694 
yank_on_j_kakutei_mode(SDLSKK_Context * context,char key)695 static void yank_on_j_kakutei_mode( SDLSKK_Context* context, char key )
696 {
697   if( context->prefix->len > 0 )
698     return;
699   yank_on_latin_mode( context, key );
700 }
701 
max2(x,y)702 static int max2( x, y ){
703   return (x>y)?x:y;
704 }
min2(x,y)705 static int min2( x, y ){
706   return (x<y)?x:y;
707 }
708 
Context_begin_region(SDLSKK_Context * context)709 static int Context_begin_region( SDLSKK_Context* context )
710 {
711   return min2( context->marked_point, context->cursor_pos );
712 }
Context_end_region(SDLSKK_Context * context)713 static int Context_end_region( SDLSKK_Context* context )
714 {
715   return max2( context->marked_point, context->cursor_pos );
716 }
717 
Context_copy_to_buffer(SDLSKK_Context * context)718 static void Context_copy_to_buffer( SDLSKK_Context* context )
719 {
720   int begin_region = Context_begin_region( context );
721   int end_region = Context_end_region( context );
722 
723   if( begin_region == end_region ){
724     SDLSKK_XStr_clear( context->cut_buffer );
725   }else{
726     SDLSKK_XStr_slice_Str( context->cut_buffer, context->str->buf,
727 			   begin_region, end_region -1 );
728   }
729 }
730 
cut_on_latin_mode(SDLSKK_Context * context,char key)731 static void cut_on_latin_mode( SDLSKK_Context* context, char key )
732 {
733   int begin_region = Context_begin_region( context );
734   int end_region = Context_end_region( context );
735   int i;
736 
737   if( context->marked_point == NOT_MARKED )
738     return;
739 
740   Context_copy_to_buffer( context );
741   Context_unset_mark( context );
742   context->cursor_pos = end_region;
743   for( i=0; i < end_region - begin_region; ++i )
744     backspace_on_latin_mode( context, 0 );
745 }
746 
copy_on_latin_mode(SDLSKK_Context * context,char key)747 static void copy_on_latin_mode( SDLSKK_Context* context, char key )
748 {
749   if( context->marked_point == NOT_MARKED )
750     return;
751 
752   Context_copy_to_buffer( context );
753 }
754 
mark_on_latin_mode(SDLSKK_Context * context,char key)755 static void mark_on_latin_mode( SDLSKK_Context* context, char key )
756 {
757   context->marked_point = context->cursor_pos;
758 }
mark_on_j_kakutei_mode(SDLSKK_Context * context,char key)759 static void mark_on_j_kakutei_mode( SDLSKK_Context* context, char key )
760 {
761   if( context->prefix->len > 0 )
762     return ;
763   context->marked_point = context->cursor_pos;
764 }
765 
beginning_of_line_on_latin_mode(SDLSKK_Context * context,char key)766 static void beginning_of_line_on_latin_mode( SDLSKK_Context* context, char key )
767 {
768   context->cursor_pos = 0;
769 }
770 
beginning_of_line_on_j_kakutei_mode(SDLSKK_Context * context,char key)771 static void beginning_of_line_on_j_kakutei_mode( SDLSKK_Context* context, char key )
772 {
773   if( context->prefix->len > 0 ){
774     SDLSKK_XStr_clear( context->prefix );
775   }
776   context->cursor_pos = 0;
777 }
778 
end_of_line_on_latin_mode(SDLSKK_Context * context,char key)779 static void end_of_line_on_latin_mode( SDLSKK_Context* context, char key )
780 {
781   context->cursor_pos = context->str->len;
782 }
783 
end_of_line_on_j_kakutei_mode(SDLSKK_Context * context,char key)784 static void end_of_line_on_j_kakutei_mode( SDLSKK_Context* context, char key )
785 {
786   if( context->prefix->len > 0 ){
787     SDLSKK_XStr_clear( context->prefix );
788   }
789   context->cursor_pos = context->str->len;
790 }
791 
SDLSKK_Context_input_event(SDLSKK_Context * context,SDL_Event * event)792 void SDLSKK_Context_input_event( SDLSKK_Context* context,SDL_Event* event )
793 {
794   if( event->key.keysym.sym < SDLK_FIRST || event->key.keysym.sym > SDLK_LAST )
795     return;
796 
797   if( context->child_context != NULL ){
798     SDLSKK_Context_input_event( context->child_context, event );
799     return;
800   }
801   if( event->type == SDL_KEYDOWN ){
802     SDLSKK_Command function;
803     function = SDLSKK_Keybind_get_command( context->keybind,
804 					   event->key.keysym, context->mode );
805     if( function != NULL )
806       function( context, event->key.keysym.unicode );
807   }
808 }
809 
810 
SDLSKK_Context_input_key(SDLSKK_Context * context,char key)811 void SDLSKK_Context_input_key( SDLSKK_Context* context, char key )
812 {
813   if( key < 0 )
814     return;
815 
816   if( context->child_context != NULL ){
817     SDLSKK_Context_input_key( context->child_context, key );
818     return;
819   }
820 
821  {
822    SDLSKK_Command function;
823    SDL_keysym keysym = {0,0,0,0};
824    if( iscntrl( key ) ){
825      keysym.mod = KMOD_CTRL;
826      keysym.sym = key + 'a' - 1;
827    }
828    keysym.unicode = key;
829    function = SDLSKK_Keybind_get_command( context->keybind, keysym,
830 					  context->mode );
831    if( function != NULL )
832      function( context, key );
833  }
834 
835 }
836 
837 struct CommandStrTable {
838   char str[35];
839   SDLSKK_Command commands[7];
840 };
841 
842 #include "command_str.tbl"
843 
SDLSKK_convert_command_str(char * command_str)844 SDLSKK_Command* SDLSKK_convert_command_str( char* command_str )
845 {
846   int i;
847 
848   for( i=0; strcmp( command_tbl[i].str, "" ) != 0; ++i ){
849     if( strcmp( command_tbl[i].str, command_str ) == 0 )
850       return command_tbl[i].commands;
851   }
852   return NULL;
853 }
854 
855 
henkan_marker()856 static SDLSKK_Char henkan_marker()
857 {
858   static const SDLSKK_Char marker_char[3] = {
859     (162<<8)+166,
860     0x25BD,
861     (129<<8)+164,
862   };
863   return marker_char[ SDLSKK_get_encoding() ];
864 }
henkan_active_marker()865 static SDLSKK_Char henkan_active_marker()
866 {
867   static const SDLSKK_Char active_marker_char[3] = {
868     (162<<8)+167,
869     0x25BC,
870     (129<<8)+165,
871   };
872   return active_marker_char[ SDLSKK_get_encoding() ];
873 }
874 
format_henkan_XStr_on_j_henkan_on_mode(SDLSKK_Context * context,SDLSKK_XStr * xstr)875 static void format_henkan_XStr_on_j_henkan_on_mode( SDLSKK_Context* context, SDLSKK_XStr* xstr )
876 {
877   SDLSKK_Char* henkan_key_katakana;
878 
879   SDLSKK_XStr_insert_Str( xstr, 0, context->prefix->buf );
880   if( context->katakana_on ){
881     henkan_key_katakana =
882       SDLSKK_Str_hiragana_to_katakana( context->henkan_key->buf );
883     SDLSKK_XStr_insert_Str( xstr, 0, henkan_key_katakana );
884     free( henkan_key_katakana );
885   }else{
886     SDLSKK_XStr_insert_Str( xstr, 0, context->henkan_key->buf );
887   }
888   SDLSKK_XStr_insert_Char( xstr, 0, henkan_marker() );
889 }
890 
format_henkan_XStr_on_j_henkan_okuri_mode(SDLSKK_Context * context,SDLSKK_XStr * xstr)891 static void format_henkan_XStr_on_j_henkan_okuri_mode( SDLSKK_Context* context, SDLSKK_XStr* xstr )
892 {
893   SDLSKK_Char* henkan_key_katakana;
894   SDLSKK_Char* henkan_okurigana_katakana;
895 
896   SDLSKK_XStr_insert_Str( xstr, 0, context->prefix->buf );
897   if( context->katakana_on ){
898     henkan_key_katakana =
899       SDLSKK_Str_hiragana_to_katakana( context->henkan_key->buf );
900     henkan_okurigana_katakana =
901       SDLSKK_Str_hiragana_to_katakana( context->henkan_okurigana->buf );
902     SDLSKK_XStr_insert_Str( xstr, 0, henkan_okurigana_katakana );
903     SDLSKK_XStr_insert_Char( xstr, 0, '*' );
904     SDLSKK_XStr_insert_Str( xstr, 0, henkan_key_katakana );
905     free( henkan_key_katakana );
906     free( henkan_okurigana_katakana );
907   }else{
908     SDLSKK_XStr_insert_Str( xstr, 0, context->henkan_okurigana->buf );
909     SDLSKK_XStr_insert_Char( xstr, 0, '*' );
910     SDLSKK_XStr_insert_Str( xstr, 0, context->henkan_key->buf );
911   }
912   SDLSKK_XStr_insert_Char( xstr, 0, henkan_marker() );
913 }
914 
SDLSKK_Context_get_henkan_XStr(SDLSKK_Context * context,SDLSKK_XStr * xstr)915 void SDLSKK_Context_get_henkan_XStr( SDLSKK_Context* context, SDLSKK_XStr* xstr )
916 {
917   SDLSKK_XStr_clear( xstr );
918 
919   switch( context->mode ){
920   case SDLSKK_LATIN_MODE:
921     break;
922   case SDLSKK_J_KAKUTEI_MODE:
923     SDLSKK_XStr_insert_Str( xstr, 0, context->prefix->buf );
924     break;
925   case SDLSKK_J_HENKAN_ON_MODE:
926     format_henkan_XStr_on_j_henkan_on_mode( context, xstr );
927     break;
928   case SDLSKK_J_HENKAN_OKURI_MODE:
929     format_henkan_XStr_on_j_henkan_okuri_mode( context, xstr );
930     break;
931   case SDLSKK_J_HENKAN_ACTIVE_MODE:
932     if( ! Context_is_in_minibuffer_wordselect_mode( context ) ){
933       SDLSKK_XStr_insert_Str( xstr, 0, context->henkan_okurigana->buf );
934       SDLSKK_XStr_insert_Str( xstr, 0, SDLSKK_DictItem_get_current( context->dict_item ) );
935     }
936     SDLSKK_XStr_insert_Char( xstr, 0, henkan_active_marker() );
937     break;
938   case SDLSKK_JISX0208_LATIN_MODE:
939     break;
940   case SDLSKK_ABBREV_MODE:
941     SDLSKK_XStr_insert_Str( xstr, 0, context->henkan_key->buf );
942     SDLSKK_XStr_insert_Char( xstr, 0, henkan_marker() );
943     break;
944   }
945 }
SDLSKK_Context_get_display_Str(SDLSKK_Context * context)946 SDLSKK_Char* SDLSKK_Context_get_display_Str( SDLSKK_Context* context )
947 {
948   SDLSKK_XStr* converting_str;
949 
950   if( context->child_context != NULL && !context->use_minibuffer ){
951     return SDLSKK_Context_get_display_Str( context->child_context );
952   }
953   converting_str = SDLSKK_XStr_new4( "", 1024 );
954   SDLSKK_XStr_copy_Str( context->display_str, context->str->buf );
955   SDLSKK_Context_get_henkan_XStr( context, converting_str );
956   SDLSKK_XStr_insert_Str( context->display_str, context->cursor_pos,
957 			  converting_str->buf );
958   SDLSKK_XStr_delete( converting_str );
959   return context->display_str->buf;
960 }
961 
XStr_concat_Char(SDLSKK_XStr * str,SDLSKK_Char ch)962 static void XStr_concat_Char( SDLSKK_XStr* str, SDLSKK_Char ch )
963 {
964   SDLSKK_XStr_insert_Char( str, str->len, ch );
965 }
966 
SDLSKK_Context_get_minibuffer_Str(SDLSKK_Context * context)967 SDLSKK_Char* SDLSKK_Context_get_minibuffer_Str( SDLSKK_Context* context )
968 {
969   int i;
970   SDLSKK_DictionaryItem item;
971   static const char asdfjkl[] = { 'A', 'S', 'D', 'F', 'J', 'K', 'L', };
972 
973   if( ! context->use_minibuffer )
974     return NULL;
975 
976   if( context->child_context != NULL )
977     return SDLSKK_Context_get_display_Str( context->child_context );
978 
979   if( Context_is_in_minibuffer_wordselect_mode( context ) ){
980     item = *(context->dict_item);
981     SDLSKK_XStr_clear( context->minibuffer_str );
982     for( i=0; i < MINIBUFFER_WORDSELECT_MAX_WORDS; ++i ){
983       XStr_concat_Char( context->minibuffer_str, asdfjkl[i] );
984       XStr_concat_Char( context->minibuffer_str, ':' );
985       SDLSKK_XStr_concat_Str( context->minibuffer_str,
986 			      SDLSKK_DictItem_get_current( &item ) );
987       XStr_concat_Char( context->minibuffer_str, ' ' );
988       if( SDLSKK_DictItem_is_end( &item ) )
989 	break;
990 
991       SDLSKK_DictItem_next( &item );
992     }
993 
994     return context->minibuffer_str->buf;
995   }
996 
997   return NULL;
998 }
999 
SDLSKK_Context_get_display_str(SDLSKK_Context * context,char * cstr,size_t size)1000 char* SDLSKK_Context_get_display_str( SDLSKK_Context* context, char* cstr,
1001 				      size_t size )
1002 {
1003   SDLSKK_Char* str;
1004   str = SDLSKK_Context_get_display_Str( context );
1005   return SDLSKK_Str_to_cstr( str, cstr, size );
1006 }
1007 
SDLSKK_Context_get_str(SDLSKK_Context * context,char * cstr,size_t size)1008 char* SDLSKK_Context_get_str( SDLSKK_Context* context, char* cstr,
1009 			      size_t size )
1010 {
1011   return SDLSKK_Str_to_cstr( context->str->buf, cstr, size );
1012 }
1013 
SDLSKK_Context_get_basic_mode(SDLSKK_Context * context)1014 int SDLSKK_Context_get_basic_mode( SDLSKK_Context* context )
1015 {
1016   switch( context->mode ){
1017   case SDLSKK_J_KAKUTEI_MODE:
1018     return ( context->prefix->len == 0 );
1019   case SDLSKK_J_HENKAN_ON_MODE:
1020   case SDLSKK_J_HENKAN_OKURI_MODE:
1021   case SDLSKK_J_HENKAN_ACTIVE_MODE:
1022   case SDLSKK_ABBREV_MODE:
1023     return 0;
1024   case SDLSKK_LATIN_MODE:
1025   case SDLSKK_JISX0208_LATIN_MODE:
1026     return 1;
1027   default:
1028     return 0;
1029   }
1030 }
1031 
SDLSKK_Context_clear(SDLSKK_Context * context)1032 void SDLSKK_Context_clear( SDLSKK_Context* context )
1033 {
1034   context->mode = SDLSKK_J_KAKUTEI_MODE;
1035   SDLSKK_XStr_clear( context->str );
1036   SDLSKK_XStr_clear( context->prefix );
1037   SDLSKK_XStr_clear( context->henkan_key );
1038   SDLSKK_XStr_clear( context->henkan_okurigana );
1039   if( context->dict_item != NULL ){
1040     SDLSKK_DictItem_delete( context->dict_item );
1041     context->dict_item = NULL;
1042   }
1043   SDLSKK_XStr_clear( context->display_str );
1044   SDLSKK_XStr_clear( context->minibuffer_str );
1045   context->cursor_pos = 0;
1046   context->henkan_buf_pos = 0;
1047   context->katakana_on = 0;
1048   if( context->child_context != NULL ){
1049     SDLSKK_Context_delete( context->child_context );
1050     context->child_context = NULL;
1051   }
1052   context->parent_context = NULL;
1053   SDLSKK_XStr_clear( context->cut_buffer );
1054   context->marked_point = NOT_MARKED;
1055 }
1056 
SDLSKK_Context_clear_text(SDLSKK_Context * context)1057 int SDLSKK_Context_clear_text( SDLSKK_Context* context )
1058 {
1059   SDLSKK_Mode old_mode;
1060   SDLSKK_XStr* old_cut_buffer;
1061 
1062   if( !SDLSKK_Context_get_basic_mode( context ) )
1063     return 0;
1064 
1065   old_mode = context->mode;
1066   old_cut_buffer = SDLSKK_XStr_new1( context->cut_buffer->buf );
1067 
1068   SDLSKK_Context_clear( context );
1069 
1070   context->mode = old_mode;
1071   SDLSKK_XStr_copy_Str( context->cut_buffer, old_cut_buffer->buf );
1072   SDLSKK_XStr_delete( old_cut_buffer );
1073 
1074   return 1;
1075 }
1076