Back to index

im-sdk  12.3.91
koif.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2003 Sun Microsystems Inc.
00003  *
00004  * This is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  *
00019  * Authors: Karl Park <karl.park@sun.com>
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025 
00026 #include <IMProtocolStruct.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <assert.h>
00030 #include "koinput.h"
00031 #include "koif_prv.h"
00032 #include "composer.h"
00033 #include "hangul.h"
00034 #include "hhdict.h"
00035 #include "lookupbuf.h"
00036 #include "utfchar.h"
00037 #include "configapi.h"
00038 #include "kolelog.h"
00039 
00040 
00041 static Bool hangul_engine_start (int n, KOLE_config **config);
00042 static Bool hangul_engine_get_hotkeys (int *n_count, IMEKeyEventStruct ***keylist);
00043 static Bool hangul_engine_finish (void);
00044 
00045 static IMEBuffer __imebuffer_new (void);
00046 static Bool hangul_imebuffer_new (IMEBuffer *new_buffer, int new_session_id,
00047                               int reuqest_engine_id);
00048 static Bool hangul_imebuffer_initialize (IMEBuffer a_buffer);
00049 static Bool hangul_imebuffer_conversion_start (IMEBuffer a_buffer);
00050 static Bool hangul_imebuffer_conversion_end (IMEBuffer a_buffer);
00051 
00052 static Bool hangul_imebuffer_get_session_id (IMEBuffer a_buffer,
00053                                         int *session_id_return);
00054 static Bool hangul_imebuffer_get_engine_id (IMEBuffer a_buffer,
00055                                        int *engine_id_return);
00056 static Bool hangul_imebuffer_get_input_mode (IMEBuffer, INPUT_MODE_T *);
00057 static Bool hangul_imebuffer_get_keyboard_layout (IMEBuffer, KEYBOARD_LAYOUT_T *);
00058 
00059 static Bool hangul_imebuffer_set_keyboard_layout (IMEBuffer a_buffer,
00060                                             KEYBOARD_LAYOUT_T *keyboard_layout);
00061 static Bool hangul_imebuffer_get_active_repertoire (IMEBuffer, OPTION_CHARSET *);
00062 static Bool hangul_imebuffer_set_active_repertoire (IMEBuffer, OPTION_CHARSET *);
00063 static Bool hangul_imebuffer_get_deletion_option (IMEBuffer, OPTION_DELETION *);
00064 static Bool hangul_imebuffer_get_commitmode_option (IMEBuffer, OPTION_DELETION *);
00065 static Bool hangul_imebuffer_get_preedit (IMEBuffer a_buffer, UTFCHAR **out_utfstr);
00066 static Bool hangul_imebuffer_get_status (IMEBuffer a_buffer,
00067                                     UTFCHAR **status_return);
00068 static Bool hangul_imebuffer_get_commit_string (IMEBuffer a_buffer,
00069                                           UTFCHAR **commit_string_return);
00070 static Bool hangul_imebuffer_get_candidates (IMEBuffer a_buffer, 
00071                                         int *n_candidates_return,
00072                                         UTFCHAR ***candidates_list_return);
00073 static Bool hangul_imebuffer_lookup_do_next_page (IMEBuffer a_buffer,
00074                                             int *new_page_num_return);
00075 static Bool hangul_imebuffer_lookup_do_previous_page (IMEBuffer a_buffer,
00076                                                 int *new_page_num_return);
00077 static Bool hangul_imebuffer_lookup_do_scroll (IMEBuffer a_buffer);
00078 static Bool hangul_imebuffer_lookup_do_select_candidate (IMEBuffer a_buffer,
00079                                                   IMEKeyEventStruct *iiim_key_event);
00080 static Bool hangul_imebuffer_lookup_get_current_candidate (IMEBuffer a_buffer,
00081                                                     int *lookup_position_return);
00082 static Bool hangul_imebuffer_process_key_input (IMEBuffer ime_buffer,
00083                                           IMEKeyEventStruct *iiim_key_event);
00084 
00085 static Bool hangul_imebuffer_free (IMEBuffer a_buffer);
00086 static Bool hangul_imebuffer_get_what_to_do (IMEBuffer ime_buffer,
00087                                         IMEBufferWhatToDo **to_do_list);
00088 
00089 static Bool hangul_imebuffer_set_what_to_do (IMEBuffer ime_buffer,
00090                                         IMEBufferWhatToDo *new_to_do_list);
00091 
00092 
00093 static Bool hangul_imebuffer_free_lookup_buffer(LookupBufferStruct *lookup_buffer, int *number_of_strings_freed);
00094 
00095 static Bool hangul_imebuffer_lookup_get_candidates (IMEBuffer a_buffer,
00096                                               int *n_candidates_return,
00097                                               int *n_candidate_number_return,
00098                                               UTFCHAR ***candidates_list_return);
00099 
00100 
00101 static Bool
00102 hangul_imebuffer_do_commit (IMEBuffer a_buffer, IMEKeyEventStruct *key_event);
00103 
00104 static Bool
00105 hangul_imebuffer_lookup_get_subsidiary_candidates (IMEBuffer a_buffer, IMEKeyEventStruct *key_event);
00106 static Bool hangul_imebuffer_get_configuration (IMEBuffer, int *, KOLE_config ***pconfig);
00107 static Bool apply_kole_config_to_session (int n, KOLE_config **pconfig, Config *sconf);
00108 static void hangul_engine_print_configuration ();
00109 static void do_options (IMEBuffer pimebuffer);
00110 
00111 IMEBufferMethodsRec ime_methods = {
00112   hangul_engine_start,
00113   hangul_engine_get_hotkeys,
00114   hangul_imebuffer_new,
00115   hangul_imebuffer_initialize,
00116   hangul_imebuffer_conversion_start,
00117   hangul_imebuffer_conversion_end,
00118   hangul_imebuffer_get_session_id,
00119   hangul_imebuffer_get_engine_id,
00120   hangul_imebuffer_get_input_mode,
00121   hangul_imebuffer_get_keyboard_layout,
00122   hangul_imebuffer_set_keyboard_layout,
00123   hangul_imebuffer_get_active_repertoire,
00124   hangul_imebuffer_set_active_repertoire,
00125   hangul_imebuffer_get_deletion_option,
00126   hangul_imebuffer_get_commitmode_option,
00127   hangul_imebuffer_get_preedit,
00128   hangul_imebuffer_get_status,
00129   hangul_imebuffer_get_commit_string,
00130   hangul_imebuffer_lookup_get_candidates,
00131   hangul_imebuffer_lookup_do_next_page,
00132   hangul_imebuffer_lookup_do_previous_page,
00133   hangul_imebuffer_lookup_do_scroll,
00134   hangul_imebuffer_lookup_do_select_candidate,
00135   hangul_imebuffer_lookup_get_current_candidate,
00136   hangul_imebuffer_process_key_input,
00137   hangul_imebuffer_free,
00138   hangul_imebuffer_get_what_to_do,
00139   hangul_imebuffer_set_what_to_do,
00140   hangul_imebuffer_get_configuration,
00141   hangul_engine_finish
00142 };
00143 
00144 static Bool hangul_engine_configure (int n, KOLE_config **config);
00145 static void hangul_engine_configure_default (void);
00146 
00147 static Bool do_search_candidates (IMEBuffer imebuffer);
00148 static Bool is_printable_commit_character (IMEKeyEventStruct *iiim_key_event);
00149 
00150 static Bool hangul_imebuffer_free_commit_buffer (IMEBuffer a_buffer);
00151 
00152 static INPUT_COMMAND_TYPE_H hangul_buffer_get_keyevent_type (IMEBuffer a_buffer,
00153                                                      IMEKeyEventStruct *key_event);
00154 
00155 static Bool hangul_buffer_lookup_selection_is_valid (IMEBuffer a_buffer,
00156                                                IMEKeyEventStruct *key_event);
00157 static Bool hangul_imebuffer_lookup_cancel_lookup (IMEBuffer a_buffer);
00158 
00159 static int default_number_of_item_per_lookup_page = 10;
00160 static int default_value_of_first_candidate = '0';
00161 
00162 
00163 /* Keypad number related convenience functions */
00164 static Bool is_keypad_num (int keycode);
00165 static int map_keypad_num_to_regular_num (int keycode);
00166 
00167 
00168 unsigned int g_engine_start_counter = 0;
00169 
00170 static Dictionary hhdict = { 0, NULL };
00171 static int g_n_config = KOLE_OPTION_TYPE_COUNT;
00172 static KOLE_config *g_engine_config[KOLE_OPTION_TYPE_COUNT];
00173 
00174 static void node_print (void *data);
00175 
00176 static Bool
00177 hangul_engine_start (int n, KOLE_config **config)
00178 {
00179     char dic_path[256];
00180     Bool mthd_return;
00181 
00182     g_engine_start_counter++;
00183   
00184     if (g_engine_start_counter > 1)
00185        return True;
00186  
00187     sprintf (dic_path, "%s/data/%s",
00188             LE_IME_MODULES_DIR,
00189             DEFAULT_DICT_NAME);
00190   
00191     mthd_return = construct_binary_tree_from_file
00192        (dic_path, &hhdict.p_trees, &hhdict.n_trees);
00193 
00194 #if 0
00195     tree_print (hhdict.p_trees, (void * (*) (void *)) node_print);
00196 #endif
00197 
00198     if (!mthd_return)
00199        return False;
00200 
00201     mthd_return = hangul_engine_configure (n, config);
00202     /* for debugging purpose */
00203     hangul_engine_print_configuration ();    
00204 
00205     if (!mthd_return){
00206       KOLE_LOG (LOGDEST_STDERR, "failed to set configuration of engine");
00207       return False;
00208     }
00209     
00210     return True;
00211 }
00212 
00213 static Bool
00214 hangul_engine_get_hotkeys (int *n_count, IMEKeyEventStruct ***keylist)
00215 {
00216   int i;
00217   int x = 0;
00218   *n_count = 4;
00219   *keylist = (IMEKeyEventStruct **) calloc (4, sizeof (IMEKeyEventStruct *));
00220   for (i = 0; i < *n_count; i++)
00221     (*keylist)[i] = (IMEKeyEventStruct *) malloc (sizeof (IMEKeyEventStruct));
00222 
00223   (*keylist)[0]->key_code = IM_VK_F2;
00224   (*keylist)[0]->key_char = 0x0;
00225   (*keylist)[0]->key_modifier = IM_SHIFT_MASK;
00226   
00227   (*keylist)[1]->key_code = IM_VK_F3;
00228   (*keylist)[1]->key_char = 0x0;
00229   (*keylist)[1]->key_modifier = IM_SHIFT_MASK;
00230   
00231   (*keylist)[2]->key_code = IM_VK_F7;
00232   (*keylist)[2]->key_char = 0x0;
00233   (*keylist)[2]->key_modifier =IM_SHIFT_MASK;
00234   
00235   (*keylist)[3]->key_code = IM_VK_F8;
00236   (*keylist)[3]->key_char = 0x0;
00237   (*keylist)[3]->key_modifier = 0x0;
00238   
00239   return True;
00240 }
00241 
00242 static Bool
00243 hangul_engine_configure (int n, KOLE_config **config)
00244 {
00245   int i;
00246   int n_option;
00247   KOLE_option_type otype;
00248 
00249   hangul_engine_configure_default ();
00250   
00251   if ( (n > g_n_config) ||
00252        (n <= 0) ||
00253        !config){
00254     /*
00255       passed values are not correct, thus
00256       set all options to default
00257      */
00258     fprintf (stderr,"hangul_engine_configure : setting option to default\n");
00259     return True;
00260   } else {
00261     if (n < g_n_config)
00262       n_option = n;
00263     else
00264       n_option = g_n_config;
00265     
00266     for (i = 0 ; i < n_option; i++){
00267 
00268       otype = config[i]->type;
00269       if (g_engine_config[otype]){
00270        /* remove them */
00271        leoption_delete (g_engine_config[otype]);
00272       }
00273       g_engine_config[otype] = leoption_copy (config[i]);
00274     }
00275   }
00276   return True;
00277 }
00278 
00279 static void
00280 hangul_engine_configure_default (void)
00281 {
00282   /* FIXME */
00283   int i = 0;
00284   
00285   for (i = 0; i < g_n_config; i++){
00286     switch (i){
00287     case KOLE_OPTION_TYPE_KEYBOARD:
00288       g_engine_config[i] =
00289        leoption_make_option_with_value (i,STR_KEYBOARD_LAYOUT_2PAIR);
00290       break;
00291     case KOLE_OPTION_TYPE_CHARSET:
00292       g_engine_config[i] =
00293        leoption_make_option_with_value (i,STR_CHARSET_UNICODE);
00294       break;
00295     case KOLE_OPTION_TYPE_DELETION:
00296       g_engine_config[i] =
00297        leoption_make_option_with_value (i, STR_DELETION_BY_JASO_NO);
00298       break;
00299     case KOLE_OPTION_TYPE_CHARBASED_COMMIT:
00300       g_engine_config[i] =
00301        leoption_make_option_with_value (i, STR_COMMITMODE_BY_HOTKEY);
00302       break;
00303     }
00304   }
00305   return;
00306 }
00307 
00308 static Bool
00309 hangul_engine_finish (void)
00310 {
00311   int i;
00312   g_engine_start_counter--;
00313   if (g_engine_start_counter > 0)
00314     return True;
00315 
00316   for (i = 0 ; i < hhdict.n_trees; i++)
00317     tree_clear (&hhdict.p_trees[i]);
00318 
00319   hhdict.n_trees = 0;
00320   free (hhdict.p_trees);
00321   hhdict.p_trees = NULL;
00322   
00323   return True;
00324 }
00325 
00326 static IMEBuffer
00327 __imebuffer_new (void)
00328 {
00329   IMEBuffer new_buffer;
00330   new_buffer = (IMEBuffer ) calloc(1, sizeof (IMEBufferRec));
00331   assert(new_buffer != NULL);
00332   if (new_buffer == NULL){
00333     /* memory allocation error */
00334     return NULL;
00335   }
00336   return new_buffer;
00337        
00338 }
00339 
00340 static Bool
00341 hangul_imebuffer_new (IMEBuffer *new_buffer, int new_session_id, int request_engine_id)
00342 {
00343   assert(new_buffer != NULL);
00344 
00345   assert (new_session_id >= 0);
00346 
00347   if (!new_buffer)
00348     return False;
00349 
00350   /* make sure *new_buffer is not referencing anything */
00351   assert(*new_buffer == NULL);
00352 
00353   /* if *new_buffer is pointing something,
00354      try to free what was being pointed,
00355      and create a new one
00356   */   
00357   if (*new_buffer){
00358     hangul_imebuffer_free(*new_buffer);
00359   }
00360 
00361   *new_buffer = __imebuffer_new();
00362 
00363   assert (*new_buffer != NULL);
00364 
00365   (*new_buffer)->session_id = new_session_id;
00366   (*new_buffer)->engine_id = request_engine_id;
00367   (*new_buffer)->input_mode = INPUT_MODE_ENGLISH;
00368   
00369 #if 0
00370   (*new_buffer)->config.charset = IN_UNICODE;
00371   (*new_buffer)->config.deletion = BY_CHAR;
00372   (*new_buffer)->config.keyboard = LAYOUT_2PART;
00373 #endif
00374   
00375   apply_kole_config_to_session (g_n_config, g_engine_config,
00376                             &((*new_buffer)->config));
00377   (*new_buffer)->what_to_do.do_preedit = False;
00378   (*new_buffer)->what_to_do.do_status = False;
00379   (*new_buffer)->what_to_do.do_lookup = False;
00380   (*new_buffer)->what_to_do.do_commit = False;
00381   (*new_buffer)->what_to_do.do_sendback = False;
00382 
00383   composer_hangul_buffer_initialize ( &((*new_buffer)->composer_buffer) );
00384 
00385   if (*new_buffer == NULL)
00386     return False;
00387   else
00388     return True;
00389 }
00390 
00391 static Bool
00392 hangul_imebuffer_initialize (IMEBuffer a_buffer)
00393 {
00394   assert (a_buffer != NULL);
00395 
00396   if(a_buffer == NULL){
00397     return False;
00398   }
00399 
00400   a_buffer->input_mode = INPUT_MODE_ENGLISH;
00401 
00402   a_buffer->what_to_do.do_lookup = False;
00403   a_buffer->what_to_do.do_preedit = False;
00404   a_buffer->what_to_do.do_lookup = False;
00405   a_buffer->what_to_do.do_preedit = False;
00406   a_buffer->what_to_do.do_sendback = False;
00407 
00408   /* clear LookupBuffer /HANGULBuffer/ Commit string */
00409   hangul_imebuffer_free_lookup_buffer (a_buffer->lookup_buffer, NULL);
00410   a_buffer->lookup_buffer = NULL;
00411   
00412   composer_hangul_buffer_initialize (&(a_buffer->composer_buffer));
00413   hangul_imebuffer_free_commit_buffer (a_buffer);
00414 
00415   return True;
00416 }
00417 
00418 
00419 static Bool
00420 hangul_imebuffer_free_commit_buffer (IMEBuffer a_buffer)
00421 {
00422   assert (a_buffer != NULL);
00423 
00424   if (a_buffer->commit_string){
00425     free (a_buffer->commit_string);
00426     a_buffer->commit_string = NULL;
00427   }
00428   return True;
00429 }
00430 
00431 static Bool
00432 hangul_imebuffer_conversion_start (IMEBuffer a_buffer)
00433 {
00434   assert (a_buffer != NULL);
00435   hangul_imebuffer_initialize (a_buffer);
00436   a_buffer->input_mode = INPUT_MODE_HANGUL;
00437 
00438   a_buffer->what_to_do.do_status = True;
00439   return True;
00440 }
00441 
00442 static Bool
00443 hangul_imebuffer_conversion_end (IMEBuffer a_buffer)
00444 {
00445   assert (a_buffer != NULL);
00446   a_buffer->input_mode = INPUT_MODE_ENGLISH;
00447   hangul_imebuffer_initialize (a_buffer);
00448   a_buffer->what_to_do.do_status = True;
00449   
00450   return True;
00451 }
00452 
00453 
00454 
00455 static Bool
00456 hangul_imebuffer_get_session_id (IMEBuffer a_buffer, int *session_id_return)
00457 {
00458   assert (a_buffer != NULL);
00459   if (a_buffer == NULL)
00460     return False;
00461   assert (session_id_return != NULL);
00462   if (session_id_return == NULL)
00463     return False;
00464 
00465   *session_id_return = a_buffer->session_id;
00466   return True;
00467 }
00468 
00469 static Bool
00470 hangul_imebuffer_get_engine_id (IMEBuffer a_buffer, int *engine_id_return)
00471 {
00472     assert (a_buffer != NULL);
00473     if (a_buffer == NULL)
00474        return False;
00475     assert (engine_id_return != NULL);
00476     if (engine_id_return == NULL)
00477        return False;
00478 
00479     assert (a_buffer->engine_id >= 0);
00480     if (a_buffer->engine_id < 0){
00481        fprintf(stderr, 
00482               "hangul_ime_biffer_get_engine_id error: "
00483               "engine_id can't be negative\n");
00484        /* try to set the engine id to the default one */
00485        a_buffer->engine_id = 0;
00486        *engine_id_return = a_buffer->engine_id;
00487        return False;
00488     } else {
00489        *engine_id_return = a_buffer->engine_id;
00490        return True;
00491     }
00492 }
00493 
00494 static Bool
00495 hangul_imebuffer_get_input_mode (IMEBuffer a_buffer,
00496                              INPUT_MODE_T *input_mode_return)
00497 {
00498   assert (a_buffer != NULL);
00499 
00500   if (a_buffer == NULL){
00501     fprintf (stderr, "hangul_imebuffer_get_input_mode error: "
00502             "IMEBuffer is null\n");
00503     return False;
00504   }
00505 
00506   assert (input_mode_return != NULL);
00507   if (input_mode_return == NULL){
00508     fprintf (stderr, "hangul_imebuffer_get_input_mode error: "
00509             "current_input_mode is null\n");
00510     return False;
00511   }
00512   *input_mode_return = a_buffer->input_mode;
00513   return True;
00514 }
00515 
00516 static Bool
00517 hangul_imebuffer_get_keyboard_layout (IMEBuffer a_buffer,
00518                                   KEYBOARD_LAYOUT_T *keyboard_layout_return)
00519 {
00520   assert (a_buffer != NULL);
00521 
00522   if (a_buffer == NULL){
00523     fprintf (stderr, "hangul_imebuffer_get_input_mode error: "
00524             "IMEBuffer is null\n");
00525     return False;
00526   }
00527 
00528   assert (keyboard_layout_return != NULL);
00529   if (keyboard_layout_return == NULL){
00530     KOLE_LOG (LOGDEST_STDERR,
00531              "hangul_imebuffer_get_input_mode error: "
00532              "current_input_mode is null\n");
00533     return False;
00534   }
00535   *keyboard_layout_return = a_buffer->config.keyboard;
00536   return True;
00537 }
00538 
00539 static Bool
00540 hangul_imebuffer_set_keyboard_layout (IMEBuffer a_buffer,
00541                                   KEYBOARD_LAYOUT_T *keyboard_layout)
00542 {
00543   assert (a_buffer != NULL);
00544 
00545   if (a_buffer == NULL){
00546     fprintf (stderr, "hangul_imebuffer_get_input_mode error: "
00547             "IMEBuffer is null\n");
00548     return False;
00549   }
00550 
00551   assert (keyboard_layout != NULL);
00552   if (keyboard_layout == NULL){
00553     KOLE_LOG (LOGDEST_STDERR,
00554              "hangul_imebuffer_set_keyboard_layout error: "
00555              "keyboard_layout is null\n");
00556     return False;
00557   }
00558   a_buffer->config.keyboard = *keyboard_layout;
00559   return True;
00560 }
00561 
00562 
00563 
00564 static Bool
00565 hangul_imebuffer_get_active_repertoire (IMEBuffer a_buffer,
00566                                    OPTION_CHARSET *charset_return)
00567 {
00568   assert (a_buffer != NULL);
00569 
00570   if (a_buffer == NULL){
00571     fprintf (stderr, "hangul_imebuffer_get_active_repertoire error: "
00572             "IMEBuffer is null\n");
00573     return False;
00574   }
00575 
00576   assert (charset_return != NULL);
00577   if (charset_return == NULL){
00578     KOLE_LOG (LOGDEST_STDERR,
00579              "hangul_imebuffer_get_active_repertoire error: "
00580              "charset is null\n");
00581     return False;
00582   }
00583   *charset_return = a_buffer->config.charset;
00584   return True;
00585 }
00586 
00587 static Bool
00588 hangul_imebuffer_set_active_repertoire (IMEBuffer a_buffer, OPTION_CHARSET *charset)
00589 {
00590   assert (charset != NULL);
00591   if (charset == NULL){
00592     KOLE_LOG (LOGDEST_STDERR, "hangul_imebuffer_set_active_repertoire error:");
00593     KOLE_LOG (LOGDEST_STDERR, "charset is NULL");
00594     return False;
00595   }
00596   composer_config_switch_codeset (&a_buffer->config, charset);
00597   a_buffer->what_to_do.do_status = True;
00598   return True;
00599 }
00600 
00601 static Bool
00602 hangul_imebuffer_get_deletion_option (IMEBuffer a_buffer,
00603                                  OPTION_DELETION *deloption)
00604 {
00605   assert (a_buffer != NULL);
00606 
00607   if (a_buffer == NULL){
00608     fprintf (stderr, "hangul_imebuffer_get_deletion_option error: "
00609             "IMEBuffer is null\n");
00610     return False;
00611   }
00612 
00613   assert (deloption != NULL);
00614   if (deloption == NULL){
00615     KOLE_LOG (LOGDEST_STDERR,
00616              "hangul_imebuffer_get_deletion_option error: "
00617              "deloption is null\n");
00618     return False;
00619   }
00620   *deloption = a_buffer->config.deletion;
00621   return True;
00622 }
00623 
00624 static Bool
00625 hangul_imebuffer_get_commitmode_option (IMEBuffer a_buffer,
00626                                    OPTION_DELETION *commit_option)
00627 {
00628   assert (a_buffer != NULL);
00629 
00630   if (a_buffer == NULL){
00631     fprintf (stderr, "hangul_imebuffer_get_commitmode_option error: "
00632             "IMEBuffer is null\n");
00633     return False;
00634   }
00635 
00636   assert (commit_option != NULL);
00637   if (commit_option == NULL){
00638     KOLE_LOG (LOGDEST_STDERR,
00639              "hangul_imebuffer_get_commitmode_option error: "
00640              "commit_option is null\n");
00641     return False;
00642   }
00643   *commit_option = a_buffer->config.commit_mode;
00644   return True;
00645 }
00646 /*
00647   param:
00648   out_utfchar: return UTFCHAR is allocated at heap.
00649   caller has responsibility to free it.
00650 
00651   After the function return, 
00652   if there's nothing in preedit buffer, *out_utfstr will be NULL
00653   if *out_utfstr is not NULL, there the preedit string has bee
00654   created for caller.
00655 */
00656 
00657 static Bool
00658 hangul_imebuffer_get_preedit (IMEBuffer a_buffer, UTFCHAR **out_utfstr)
00659 {
00660   int i, utfchar_len;
00661   UTFCHAR *han_char;
00662   HANGULBuffer *session_buffer;
00663   HANGUL *current_hangul;
00664 
00665   HANGUL last_hangul; /* to be deleted */
00666 
00667   assert (a_buffer != NULL);
00668 
00669   utfchar_len = composer_hangul_buffer_get_hangul_length(&a_buffer->composer_buffer);
00670   assert (utfchar_len >= 0);
00671 
00672   if (utfchar_len <= -1) {
00673     fprintf(stderr, "hangul_imebuffer_get_preedit error: number of hangul "
00674            "can't be negative\n");
00675     return False;
00676   }
00677   else if (utfchar_len == 0) {
00678     *out_utfstr = NULL;
00679     return True;
00680   }
00681   else {
00682     session_buffer = &a_buffer->composer_buffer;
00683 
00684     assert (session_buffer != NULL);
00685     if (session_buffer == NULL){
00686       fprintf(stderr, 
00687              "hangul_imebuffer_get_preedit error: composer_buffer can't be null\n");
00688       return False;
00689     }
00690               
00691     *out_utfstr = (UTFCHAR *) calloc( utfchar_len + 1 , sizeof (UTFCHAR) );
00692 
00693     for (i = 0 ; i < utfchar_len; i++) {
00694       UTFCHAR combined_character;
00695       UTFCHAR tmp;
00696       combined_character = composer_hangul_combine_cho_jung_jong( (session_buffer->buffer[i]) );
00697       if (combined_character){
00698        (*out_utfstr)[i] = combined_character;
00699       } else {
00700        current_hangul = session_buffer->buffer[i];
00701        if (!_jamo_is_clean (&current_hangul->L)){
00702          tmp = _jamo_get_value (&current_hangul->L);
00703          (*out_utfstr)[i] =
00704            hangul_combining_chosung_to_compatibility_jamo (tmp);
00705        } else if (!_jamo_is_clean (&current_hangul->V)) {
00706          tmp = _jamo_get_value (&current_hangul->V);
00707          (*out_utfstr)[i] =
00708            hangul_combining_jungsung_to_compatibility_moeum (tmp);
00709        } else if (!_jamo_is_clean (&current_hangul->T)) {
00710          tmp = _jamo_get_value (&current_hangul->T);
00711          (*out_utfstr)[i] =
00712            hangul_combining_jongsung_to_compatibility_jaeum (tmp);
00713        }
00714       }
00715     }
00716     (*out_utfstr)[i] = 0x0000;
00717   }
00718 
00719   return True;
00720 }
00721 
00722 static Bool
00723 hangul_imebuffer_get_status (IMEBuffer a_buffer, UTFCHAR **status_return)
00724 {
00725   assert (a_buffer != NULL);
00726 
00727   if (a_buffer == NULL){
00728     fprintf (stderr, "hangul_imebuffer_get_status error: imebuffer can't be null\n");
00729     *status_return = NULL;
00730     return False;
00731   }
00732   /* Fix me */
00733   if (a_buffer->input_mode == INPUT_MODE_ENGLISH) {
00734     
00735     *status_return = (UTFCHAR *) calloc (3, sizeof (UTFCHAR));
00736     (*status_return)[0] = 0xC601;
00737     (*status_return)[1] = 0xC5B4;
00738     (*status_return)[2] = 0x0000;
00739               
00740   } else if (a_buffer->input_mode == INPUT_MODE_HANGUL ){
00741     if (a_buffer->config.charset == IN_EUC){
00742       *status_return = (UTFCHAR *) calloc (6, sizeof (UTFCHAR));
00743       (*status_return)[0] = 0xD55C;
00744       (*status_return)[1] = 0xAE00;
00745       (*status_return)[2] = '[';
00746       (*status_return)[3] = 0xC644;
00747       (*status_return)[4] = ']';
00748       (*status_return)[5] = 0x0000;
00749 
00750     } else {
00751       *status_return = (UTFCHAR *) calloc (6, sizeof (UTFCHAR));
00752       (*status_return)[0] = 0xD55C;
00753       (*status_return)[1] = 0xAE00;
00754       (*status_return)[2] = '[';
00755       (*status_return)[3] = 0xC870;
00756       (*status_return)[4] = ']';
00757       (*status_return)[5] = 0x0000;
00758     }
00759   } else {
00760     /* for now, this defaults to korean */
00761     /* fix me */
00762     *status_return = (UTFCHAR *) calloc (3, sizeof (UTFCHAR));
00763     (*status_return)[0] = 0xD55C;
00764     (*status_return)[1] = 0xAE00;
00765     (*status_return)[2] = 0x0000;
00766 
00767   }
00768 
00769   return True;
00770 }
00771 
00772 static Bool
00773 hangul_imebuffer_get_commit_string (IMEBuffer a_buffer, UTFCHAR **commit_string_return)
00774 {
00775   int commit_length;
00776   assert (a_buffer != NULL);
00777   if (a_buffer->commit_string == NULL){
00778     fprintf (stderr, "hangul_imebuffer_get_commit_string error: commit string is null\n");
00779     *commit_string_return = NULL;
00780     return False;
00781   }
00782   commit_length = _utfchar_length (a_buffer->commit_string);
00783   *commit_string_return = (UTFCHAR *) calloc (commit_length + 1, sizeof (UTFCHAR) );
00784   _utfchar_copy (*commit_string_return, a_buffer->commit_string);
00785   return True;
00786 }
00787 
00788 static Bool
00789 hangul_imebuffer_lookup_get_candidates (IMEBuffer a_buffer, 
00790                                    int *n_candidates_return,
00791                                    int *n_current_candidate,
00792                                    UTFCHAR ***candidates_list_return)
00793 {
00794   LookupBufferStruct *plub;  
00795   assert (a_buffer != NULL);
00796   plub = a_buffer->lookup_buffer;
00797 
00798   hangul_lookupbuf_get_current_page_candidates
00799     (plub, n_candidates_return, n_current_candidate, candidates_list_return);
00800 
00801   if (*candidates_list_return)
00802     return True;
00803   else
00804     return False;
00805 }
00806 
00807 static Bool
00808 hangul_imebuffer_lookup_do_next_page (IMEBuffer a_buffer, int *new_page_num_return)
00809 {
00810   assert (a_buffer != NULL);
00811   if (a_buffer == NULL){
00812     fprintf (stderr, "hangul_imebuffer_lookup_do_next_page error : "
00813             "a_buffer is NULL\n");
00814     return False;
00815   }
00816 
00817   if (a_buffer->lookup_buffer == NULL){
00818     fprintf (stderr, "hangul_imebuffer_lookup_do_next_page error : "
00819             "a_buffer->lookup_buffer is NULL\n");
00820     return False;
00821   }
00822   
00823   hangul_lookupbuf_next_page (a_buffer->lookup_buffer);
00824   /* ignoring new_page_num_return */
00825   return True;
00826 
00827 }
00828 
00829 static Bool
00830 hangul_imebuffer_lookup_do_previous_page (IMEBuffer a_buffer, int *new_page_num_return)
00831 {
00832   assert (a_buffer != NULL);
00833   if (a_buffer == NULL){
00834     fprintf (stderr, "hangul_imebuffer_lookup_do_next_page error : "
00835             "a_buffer is NULL\n");
00836     return False;
00837   }
00838 
00839   if (a_buffer->lookup_buffer == NULL){
00840     fprintf (stderr, "hangul_imebuffer_lookup_do_next_page error : "
00841             "a_buffer->lookup_buffer is NULL\n");
00842     return False;
00843   }
00844   hangul_lookupbuf_previous_page (a_buffer->lookup_buffer);
00845   /* ignoring new_page_num_return */
00846   return True;
00847 }
00848 
00849 
00850 static Bool
00851 hangul_imebuffer_lookup_do_scroll (IMEBuffer a_buffer)
00852 {
00853   assert (a_buffer != NULL);
00854   if (a_buffer == NULL){
00855     fprintf (stderr, "hangul_imebuffer_lookup_do_scroll error :"
00856             "a_buffer is NULL\n");
00857     return False;
00858   }
00859   if (a_buffer->lookup_buffer == NULL){
00860     fprintf (stderr, "hangul_imebuffer_lookup_do_scroll error :"
00861             "a_buffer->lookup_buffer is NULL\n");
00862     return False;
00863   }
00864   hangul_lookupbuf_next_candidate (a_buffer->lookup_buffer);
00865   
00866   a_buffer->what_to_do.do_preedit = False;
00867   a_buffer->what_to_do.do_status = False;
00868   a_buffer->what_to_do.do_lookup = True;
00869   a_buffer->what_to_do.do_commit = False;
00870   a_buffer->what_to_do.do_sendback = False;
00871   
00872   return True;
00873 }
00874 
00875 static  Bool
00876 hangul_imebuffer_lookup_do_select_candidate (IMEBuffer a_buffer,
00877                                         IMEKeyEventStruct *key_event)
00878 {
00879   
00880   LookupBufferStruct *p_lookup_info;
00881   int selected_candidate_length;
00882   int i_selected_candidate;
00883   int key_code;
00884   int pressed_number;
00885   int available_candidates;
00886 
00887   assert (a_buffer != NULL);
00888   assert (key_event != NULL);
00889   assert (a_buffer->lookup_buffer != NULL);
00890 
00891   p_lookup_info = a_buffer->lookup_buffer;
00892        
00893   key_code = key_event->key_code;
00894 
00895   /* if number was selected to commit,
00896      I need to update the LooupBufferStruct before
00897      attempting to commit
00898   */
00899   available_candidates =
00900     hangul_lookupbuf_get_count_of_candidates_in_current_page (p_lookup_info);
00901   
00902   if (available_candidates == -1)
00903     return False;
00904 
00905   if (key_code >= IM_VK_0 && key_code <= IM_VK_9){
00906     pressed_number = key_code - default_value_of_first_candidate;
00907     if (pressed_number < 0 ||
00908        pressed_number >= available_candidates){
00909       fprintf (stderr, "hangul_imebuffer_lookup_do_select_candidate error : "
00910               "selection is out of range\n");
00911       return False;
00912     }
00913   } else if (key_code == IM_VK_ENTER){
00914     pressed_number =
00915       hangul_lookupbuf_get_current_selection_index (p_lookup_info);
00916   } else
00917     return False;
00918 
00919   
00920   a_buffer->commit_string =
00921     hangul_lookupbuf_get_candidate_string (p_lookup_info, pressed_number);
00922 
00923   hangul_imebuffer_free_lookup_buffer (p_lookup_info, NULL);
00924   p_lookup_info = NULL;
00925   a_buffer->lookup_buffer = NULL;
00926   
00927   composer_hangul_buffer_initialize (&(a_buffer->composer_buffer));
00928 
00929   a_buffer->input_mode = INPUT_MODE_HANGUL;
00930   a_buffer->what_to_do.do_lookup = False;
00931   a_buffer->what_to_do.do_preedit = False;
00932   a_buffer->what_to_do.do_commit = True;
00933   a_buffer->what_to_do.do_sendback = False;
00934   return True;
00935 }
00936 
00937 
00938 static Bool
00939 hangul_imebuffer_lookup_get_current_candidate (IMEBuffer a_buffer, int *lookup_position_return)
00940 {
00941   LookupBufferStruct *p_lb;
00942   int i;
00943 
00944   assert (a_buffer != NULL);
00945   if (a_buffer == NULL){
00946     fprintf (stderr, "hangul_imebuffer_lookup_get_current_candidate error: "
00947             "imebuffer can't be null\n");
00948     *lookup_position_return = -1;
00949     return False;
00950   }
00951 
00952   p_lb = a_buffer->lookup_buffer;
00953 
00954   assert (lookup_position_return != NULL);
00955   if (lookup_position_return == NULL){
00956     fprintf (stderr, "hangul_imebuffer_lookup_get_current_candidate error : "
00957             "lookup_position_return can't be null\n");
00958     return False;
00959   }
00960   i = hangul_lookupbuf_get_current_selection_index (p_lb);
00961   if (i == -1){
00962     *lookup_position_return = -1;
00963     return False;
00964   } else {
00965     *lookup_position_return = i;
00966     return True;
00967   }
00968 }
00969 
00970 static Bool
00971 hangul_imebuffer_process_key_input (IMEBuffer ime_buffer, IMEKeyEventStruct *iiim_key_event)
00972 {
00973   int key_code, key_char, key_modifier;
00974   int ret;
00975   HANGULBuffer *hangul_buffer = &ime_buffer->composer_buffer;
00976   LookupBufferStruct **lub;
00977   Bool method_return;
00978   INPUT_MODE_T input_mode_return;
00979   INPUT_COMMAND_TYPE_H input_command;
00980   Config *pconfig;
00981 
00982   int hangul_length;
00983   
00984   int i;
00985   int n_candidates = 0;
00986   UTFCHAR **string_list = NULL;
00987     
00988   assert (iiim_key_event != NULL);
00989 
00990   key_code = iiim_key_event->key_code;
00991   key_char = iiim_key_event->key_char;
00992   key_modifier = iiim_key_event->key_modifier;
00993 
00994   pconfig = &ime_buffer->config;
00995   hangul_imebuffer_get_input_mode(ime_buffer, &input_mode_return);
00996   KOLE_LOG(LOGDEST_STDOUT, "input_mode is %d.\n", input_mode_return);
00997 
00998   lub = &(ime_buffer->lookup_buffer);
00999   input_command = hangul_buffer_get_keyevent_type (ime_buffer, iiim_key_event);
01000   KOLE_LOG(LOGDEST_STDOUT, "input_command is %d.\n", input_command);
01001 
01002   if (input_command == INPUT_COMMAND_TURN_OFF_CONVERSION){
01003 
01004     hangul_imebuffer_initialize (ime_buffer);
01005     return True;
01006     
01007   } else if (input_command == INPUT_COMMAND_TURN_ON_CONVERSION) {
01008     
01009     hangul_imebuffer_conversion_start (ime_buffer);
01010     return True;
01011 
01012   } else if (input_command == INPUT_COMMAND_SWITCH_CODESET){
01013     /* keyevent is triggering this, thus cycling through.. */
01014     composer_config_switch_codeset (&ime_buffer->config, NULL);
01015     ime_buffer->what_to_do.do_status = True;
01016     return True;
01017     
01018   } else if (input_command == INPUT_COMMAND_SWITCH_KEYBOARD_LAYOUT){
01019     
01020     composer_config_switch_keyboard (&ime_buffer->config);
01021     KOLE_LOG(LOGDEST_STDOUT, "INPUT_COMMAND_SWITCH_KEYBOARD_LAYOUT.\n");
01022     return True;
01023     
01024   } else if (input_command == INPUT_COMMAND_SWITCH_COMMIT_METHOD){
01025  
01026     composer_config_switch_commit_method (&ime_buffer->config);
01027     return True;
01028     
01029   } else if (input_command == INPUT_COMMAND_HANJA_DO_LOOKUP) {
01030     
01031     method_return = do_search_candidates (ime_buffer);
01032     if (method_return){
01033       ime_buffer->input_mode = INPUT_MODE_HANJA;
01034       ime_buffer->what_to_do.do_lookup = True;
01035       ime_buffer->what_to_do.do_preedit = True;
01036       return True;
01037     } else
01038       return False;
01039     
01040   } else if (input_command == INPUT_COMMAND_LOOKUP_DO_NEXT_PAGE){
01041     method_return = hangul_imebuffer_lookup_do_next_page (ime_buffer, NULL);
01042          
01043     if (method_return == False)
01044       return False;
01045     else
01046       return True;
01047   } else if (input_command == INPUT_COMMAND_LOOKUP_DO_PREVIOUS_PAGE){
01048     method_return = hangul_imebuffer_lookup_do_previous_page (ime_buffer, NULL);
01049          
01050     if (method_return == False)
01051       return False;
01052     else
01053       return True;
01054          
01055   } else if (input_command == INPUT_COMMAND_LOOKUP_DO_SCROLL){
01056     hangul_imebuffer_lookup_do_scroll (ime_buffer);
01057          
01058     return True;
01059               
01060   } else if (input_command == INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE){
01061     
01062     if (ime_buffer->input_mode == INPUT_MODE_HANJA ||
01063        ime_buffer->input_mode == INPUT_MODE_SYMBOL ){
01064       hangul_imebuffer_lookup_do_select_candidate (ime_buffer,iiim_key_event);
01065     
01066     } else if (ime_buffer->input_mode == INPUT_MODE_SYMBOL_MENU){
01067       hangul_imebuffer_lookup_get_subsidiary_candidates (ime_buffer, iiim_key_event);
01068       hangul_imebuffer_lookup_do_next_page (ime_buffer, NULL);
01069       ime_buffer->input_mode = INPUT_MODE_SYMBOL;
01070       ime_buffer->what_to_do.do_lookup = True;
01071       ime_buffer->what_to_do.do_preedit = True;
01072     }
01073     
01074     return True;
01075     
01076   } else if (input_command == INPUT_COMMAND_CANCEL_LOOKUP) {
01077     hangul_imebuffer_lookup_cancel_lookup (ime_buffer);
01078     if (key_code == IM_VK_BACK_SPACE){
01079       if (composer_hangul_buffer_get_hangul_length (hangul_buffer) == 0){
01080        /* nothing to delete , this is very unlikely*/
01081        fprintf (stderr, "something very weird is going on!!!\n");
01082        return True;
01083       }
01084       composer_hangul_buffer_delete_hangul_character (hangul_buffer, True, NULL);
01085     }
01086     ime_buffer->what_to_do.do_preedit = True;
01087 
01088     return True;
01089     
01090   } else if (input_command == INPUT_COMMAND_SYMBOL_MENU_LOOKUP) {
01091 
01092     hangul_length =
01093       composer_hangul_buffer_get_hangul_length (&ime_buffer->composer_buffer);
01094 
01095     if (hangul_length > 0){
01096       if (!hangul_imebuffer_do_commit (ime_buffer, iiim_key_event))
01097        return False;
01098     }
01099     
01100     method_return =
01101       composer_symbol_menu_lookup_start (&n_candidates, &string_list);
01102     
01103     if ((method_return == False) || (n_candidates == 0))
01104       return False;
01105     
01106     *lub = 
01107       hangul_lookupbuf_new (n_candidates,
01108                          default_number_of_item_per_lookup_page,
01109                          string_list);
01110     for (i = 0 ; i < n_candidates; i++)
01111       free (string_list[i]);
01112     free (string_list);
01113 
01114     hangul_imebuffer_lookup_do_next_page (ime_buffer, NULL);
01115     ime_buffer->input_mode = INPUT_MODE_SYMBOL_MENU;
01116     ime_buffer->what_to_do.do_lookup = True;
01117     ime_buffer->what_to_do.do_preedit = True;
01118            
01119     return True;
01120   } else if (input_command == INPUT_COMMAND_NOTHING){
01121     return False;
01122   } else if (input_command == INPUT_COMMAND_IGNORE){
01123     return True;
01124   } else if (input_command == INPUT_COMMAND_COMMIT){
01125      if (key_code == IM_VK_ENTER){
01126         KOLE_LOG(LOGDEST_STDOUT, " IM_VK_IM_VK_ENTER\n");
01127            if (composer_hangul_buffer_get_hangul_length (hangul_buffer) == 0)
01128         return False; 
01129       }
01130     return hangul_imebuffer_do_commit (ime_buffer, iiim_key_event);
01131     
01132   } else if (input_command == INPUT_COMMAND_REGULAR_HANGUL){
01133 
01134     if (key_code == IM_VK_BACK_SPACE){
01135       Bool deletion_whole_character;
01136       if (composer_hangul_buffer_get_hangul_length (hangul_buffer) == 0){
01137        /* nothing to delete */
01138        return False;
01139       }
01140       if ((pconfig->deletion == BY_JASO) ||
01141          (key_modifier & IM_SHIFT_MASK)){
01142        deletion_whole_character =  False;
01143       } else
01144        deletion_whole_character =  True;
01145       
01146       composer_hangul_buffer_delete_hangul_character (hangul_buffer,
01147                                                 deletion_whole_character,
01148                                                 NULL);
01149       ime_buffer->what_to_do.do_preedit = True;
01150       
01151       return True;
01152     }
01153 
01154     switch (pconfig->keyboard){
01155     case LAYOUT_2PART:
01156       KOLE_LOG(LOGDEST_STDOUT, "LAYOUT_2PART:\n");
01157       ret = composer_hangul_automata_2pair (key_code,
01158                                        key_char,
01159                                        key_modifier,
01160                                        hangul_buffer,
01161                                        pconfig);
01162       break;
01163       
01164     case LAYOUT_3PART390:
01165       KOLE_LOG(LOGDEST_STDOUT, "LAYOUT_3PART390:\n");
01166       ret = composer_hangul_automata_3pair_final (key_code,
01167                                             key_char,
01168                                             key_modifier,
01169                                             hangul_buffer,
01170                                             pconfig, LAYOUT_3PART390);
01171 
01172       break;
01173       
01174     case LAYOUT_3PART_FINAL:
01175       KOLE_LOG(LOGDEST_STDOUT, "LAYOUT_3PART_FINAL:\n");
01176       ret = composer_hangul_automata_3pair_final (key_code,
01177                                             key_char,
01178                                             key_modifier,
01179                                             hangul_buffer,
01180                                             pconfig, LAYOUT_3PART_FINAL);
01181 
01182       break;
01183       
01184     }
01185    
01186     if(ret == ComposerRetKeep) {  /* SUCCEEDED */
01187         KOLE_LOG(LOGDEST_STDOUT, "ret is ComposerRetKeep\n");
01188        ime_buffer->what_to_do.do_preedit = True;
01189        do_options (ime_buffer);
01190        return True;
01191     } else if (ret == ComposerRetBreak) {
01192         KOLE_LOG(LOGDEST_STDOUT, "ret is ComposerRetBreak.\n");
01193       /* succeeded, but to commit preedit buffer */
01194       if (hangul_buffer->count == 0) {
01195          /* Even if there was no preedit,
01196             there's case where input has to be cooked,
01197             (like in case you entered 'backslash', expecting
01198             it to return 'korean won currency symbol'.
01199             thus I leave the if..else breanch here
01200             even if any execution path will do exactly the same.
01201          */
01202          
01203          method_return =
01204              hangul_imebuffer_do_commit (ime_buffer, iiim_key_event);
01205          return True;
01206       } else {
01207          method_return =
01208              hangul_imebuffer_do_commit (ime_buffer, iiim_key_event);
01209          return True;
01210       }
01211     } else {
01212       KOLE_LOG(LOGDEST_STDOUT, "ret is ComposerRetErr\n");
01213       return False;
01214     }
01215   }
01216 }
01217 
01218 static void
01219 do_options (IMEBuffer pimebuffer)
01220 {
01221   int i;
01222   
01223   if ((pimebuffer->config.commit_mode == COMMIT_BY_CHAR) &&
01224       (pimebuffer->composer_buffer.count > 1))
01225     {
01226       if (pimebuffer->commit_string)
01227        free (pimebuffer->commit_string);
01228 
01229       pimebuffer->commit_string =
01230        (UTFCHAR *) calloc (pimebuffer->composer_buffer.count, sizeof(UTFCHAR));
01231       for (i = 0; i < pimebuffer->composer_buffer.count - 1; i++)
01232        {
01233          HANGUL *phangul;
01234          UTFCHAR combined_character;
01235          UTFCHAR tmp;
01236          
01237          phangul = composer_hangul_buffer_pop_hangul (&pimebuffer->composer_buffer);
01238 
01239          combined_character = composer_hangul_combine_cho_jung_jong (phangul);
01240          if (combined_character){
01241            pimebuffer->commit_string[i] =
01242              composer_hangul_combine_cho_jung_jong (phangul);
01243          } else {
01244 
01245            if (!_jamo_is_clean (&phangul->L)){
01246              tmp = _jamo_get_value (&phangul->L);
01247              pimebuffer->commit_string[i] =
01248               hangul_combining_chosung_to_compatibility_jamo (tmp);
01249            } else if (!_jamo_is_clean (&phangul->V)) {
01250              tmp = _jamo_get_value (&phangul->V);
01251              pimebuffer->commit_string[i] =
01252               hangul_combining_jungsung_to_compatibility_moeum (tmp);
01253            } else if (!_jamo_is_clean (&phangul->T)) {
01254              tmp = _jamo_get_value (&phangul->T);
01255              pimebuffer->commit_string[i] =
01256               hangul_combining_jongsung_to_compatibility_jaeum (tmp);
01257            }
01258            
01259          }
01260 
01261          composer_hangul_free (phangul);
01262        }
01263       pimebuffer->what_to_do.do_commit = True;
01264     }
01265 }
01266 
01267 static Bool
01268 hangul_imebuffer_free (IMEBuffer a_buffer)
01269 {
01270   assert (a_buffer != NULL);
01271   composer_hangul_buffer_initialize (&(a_buffer->composer_buffer));
01272   hangul_imebuffer_free_lookup_buffer (a_buffer->lookup_buffer, NULL);
01273   a_buffer->lookup_buffer = NULL;
01274   return True;
01275 }
01276 
01277 static Bool
01278 hangul_imebuffer_get_what_to_do (IMEBuffer ime_buffer,IMEBufferWhatToDo **to_do_list)
01279 {
01280   assert (ime_buffer != NULL);
01281 
01282   assert (*to_do_list == NULL);
01283 
01284   *to_do_list = NULL;
01285   *to_do_list = (IMEBufferWhatToDo *) calloc (1, sizeof (IMEBufferWhatToDo ));
01286 
01287   assert (*to_do_list != NULL);
01288 
01289   (*to_do_list)->do_preedit = ime_buffer->what_to_do.do_preedit;
01290   (*to_do_list)->do_status = ime_buffer->what_to_do.do_status;
01291   (*to_do_list)->do_lookup = ime_buffer->what_to_do.do_lookup;
01292   (*to_do_list)->do_commit = ime_buffer->what_to_do.do_commit;
01293   (*to_do_list)->do_sendback = ime_buffer->what_to_do.do_sendback;
01294   return True;
01295 }
01296 
01297 static Bool
01298 hangul_imebuffer_set_what_to_do (IMEBuffer ime_buffer,
01299                              IMEBufferWhatToDo *new_to_do_list)
01300 {
01301   assert (ime_buffer != NULL);
01302 
01303   assert (new_to_do_list != NULL);
01304 
01305   ime_buffer->what_to_do.do_preedit = new_to_do_list->do_preedit;
01306   ime_buffer->what_to_do.do_status = new_to_do_list->do_status;
01307   ime_buffer->what_to_do.do_lookup = new_to_do_list->do_lookup;
01308   ime_buffer->what_to_do.do_commit = new_to_do_list->do_commit;
01309   ime_buffer->what_to_do.do_sendback = new_to_do_list->do_sendback;
01310 
01311   if (ime_buffer->what_to_do.do_commit == False){
01312       if (hangul_imebuffer_free_commit_buffer (ime_buffer) != True){
01313          return False;
01314       }
01315   }
01316   /* fix me */
01317 #if 0
01318   if (ime_buffer->what_to_do.do_preedit == False){
01319     if (ime_buffer->lookup_buffer){
01320       hangul_imebuffer_free_lookup_buffer (ime_buffer->lookup_buffer, NULL);
01321       ime_buffer->lookup_buffer = NULL;
01322     }
01323   }
01324 #endif
01325   return True;
01326 }
01327 
01328 
01329 static Bool
01330 is_keypad_num (int keycode)
01331 {
01332   if ((keycode >= IM_VK_NUMPAD0) &&
01333       (keycode <= IM_VK_NUMPAD9))
01334     return True;
01335   else
01336     return False;
01337 }
01338 
01339 static int
01340 map_keypad_num_to_regular_num (int keycode)
01341 {
01342   if (is_keypad_num (keycode))
01343     return (keycode - 0x30);
01344 }
01345 
01346 
01347 /*
01348   commit_trigger_key is not IMEKeyEventStruct key code,
01349   becuase the commit triggering key must have been
01350   re-interpreated based on the keyboard layout which is
01351   currently active.
01352 */
01353 
01354 static Bool
01355 hangul_imebuffer_do_commit (IMEBuffer a_buffer, IMEKeyEventStruct *key_event)
01356 
01357 {
01358   UTFCHAR commit_trigger_key;
01359   UTFCHAR *commit_string_return = NULL;
01360   Bool result;
01361   int preedit_length;
01362   int commit_string_length;
01363   UTFCHAR utf_input;
01364   Config *pconfig;
01365   
01366   pconfig = &a_buffer->config;
01367   if (key_event)
01368       utf_input = get_utf_input_by_keyboard (key_event, pconfig->keyboard);
01369 
01370   KOLE_LOG(LOGDEST_STDOUT, "hangul_imebuffer_do_commit(), utf_input is %x\n", utf_input);
01371   preedit_length =
01372     composer_hangul_buffer_get_hangul_length (&a_buffer->composer_buffer);
01373   commit_string_length = preedit_length;
01374   KOLE_LOG(LOGDEST_STDOUT, "hangul_imebuffer_do_commit(), commit_len is %d.\n", commit_string_length);
01375   
01376 
01377   if (preedit_length == 0){
01378       KOLE_LOG(LOGDEST_STDOUT, "hangul_imebuffer_do_commit(), preedit_lengh is zero.\n");
01379 
01380       composer_hangul_buffer_initialize (&a_buffer->composer_buffer);
01381 
01382       a_buffer->commit_string = (UTFCHAR *) calloc (2, sizeof (UTFCHAR));
01383       a_buffer->commit_string [0] = utf_input;
01384       a_buffer->commit_string [1] = 0x0000;
01385       /*
01386     fprintf (stderr,
01387             "hangul_imebuffer_do_commit error: preedit length was zero\n");
01388             return False;
01389       */
01390       a_buffer->what_to_do.do_commit = True;
01391       a_buffer->what_to_do.do_preedit = False;
01392       /*hangul_buffer_debug_print(a_buffer);*/
01393       return True;
01394 
01395   }
01396 
01397   result = hangul_imebuffer_get_preedit (a_buffer, &commit_string_return);
01398   
01399   if (result == False) {
01400     fprintf (stderr,
01401             "hangul_imebuffer_do_commit error: "
01402             "failure getting preedit string\n");
01403     return False;
01404   }
01405   if (utf_input){
01406       commit_trigger_key = utf_input;
01407       commit_string_length += 1;
01408       /*
01409        Moving the code for checking inpu being the backslash
01410        into get_utf_input_by_keyboard () becuase this is more
01411        appropriate location for this code
01412       
01413        } else if (utf_input == '\\'){
01414        commit_trigger_key = 0x20a9;
01415        commit_string_length += 1;
01416       */
01417   }
01418   else /* Extra action needs to be taken */
01419     a_buffer->what_to_do.do_sendback = True;
01420 
01421   /* free up the memory for HANGULList buffer */
01422   composer_hangul_buffer_initialize (&a_buffer->composer_buffer);
01423 
01424   a_buffer->commit_string =
01425     (UTFCHAR *) calloc (commit_string_length + 1, sizeof (UTFCHAR));
01426   _utfchar_copy (a_buffer->commit_string, commit_string_return);
01427   
01428   if (preedit_length + 1 == commit_string_length){
01429     a_buffer->commit_string [commit_string_length - 1] = commit_trigger_key;
01430     a_buffer->commit_string [commit_string_length ] = 0x0000;
01431   }
01432 
01433   hangul_imebuffer_free_lookup_buffer(a_buffer->lookup_buffer, NULL);
01434   a_buffer->lookup_buffer = NULL;
01435 
01436   free (commit_string_return);
01437   
01438   a_buffer->what_to_do.do_commit = True;
01439   a_buffer->what_to_do.do_preedit = False;
01440   
01441   return True;       
01442 }
01443 
01444 static Bool
01445 hangul_imebuffer_free_lookup_buffer (LookupBufferStruct *lookup_buffer, int *number_of_strings_freed)
01446 {
01447   Bool ret;
01448   if (lookup_buffer){
01449     ret = hangul_lookupbuf_free (lookup_buffer);
01450   }
01451   return ret;
01452 }
01453 
01454 static Bool
01455 hangul_imebuffer_lookup_get_subsidiary_candidates (IMEBuffer a_buffer,
01456                                              IMEKeyEventStruct *key_event)
01457 {
01458   LookupBufferStruct **p_lookup_info;
01459   int selected_candidate_length;
01460   int i_selected_group;
01461   int key_code;
01462   int pressed_number;
01463   int available_candidates;
01464   int i;
01465 
01466   int symbol_count = 0;
01467   UTFCHAR **symbol_list = NULL;
01468   
01469   assert (a_buffer != NULL);
01470   assert (key_event != NULL);
01471 
01472   p_lookup_info = &a_buffer->lookup_buffer;
01473        
01474   key_code = key_event->key_code;
01475 
01476   /* if number was selected to commit,
01477      I need to update the LooupBufferStruct before
01478      attempting to commit
01479   */
01480 
01481   available_candidates =
01482     hangul_lookupbuf_get_count_of_candidates_in_current_page (*p_lookup_info);
01483   
01484   if (available_candidates == -1)
01485     return False;
01486   
01487   if (key_code >= IM_VK_0 && key_code <= IM_VK_9){
01488 
01489     i_selected_group = key_code - default_value_of_first_candidate;
01490     
01491     if (i_selected_group < 0 ||
01492        i_selected_group >= available_candidates){
01493       fprintf (stderr, "hangul_imebuffer_lookup_do_select_candidate error : "
01494               "selection is out of range\n");
01495       return False;
01496     }
01497   } else if (key_code == IM_VK_ENTER){
01498     i_selected_group =
01499       hangul_lookupbuf_get_current_selection_index (*p_lookup_info);
01500   } else
01501     return False;
01502 
01503   /* free symbol menu lookup data first */
01504   hangul_imebuffer_free_lookup_buffer (*p_lookup_info, NULL);
01505   *p_lookup_info = NULL;
01506 
01507   /* get detail info for newly chosen symbol group*/
01508   composer_symbol_detail_lookup_start (i_selected_group,
01509                                    &symbol_count, &symbol_list);
01510   
01511   *p_lookup_info = 
01512     hangul_lookupbuf_new (symbol_count,
01513                        default_number_of_item_per_lookup_page,
01514                        symbol_list);
01515   for (i = 0 ; i < symbol_count; i++)
01516     free (symbol_list[i]);
01517   free (symbol_list);
01518   
01519 
01520   a_buffer->input_mode = INPUT_MODE_SYMBOL;
01521   a_buffer->what_to_do.do_lookup = True;
01522   a_buffer->what_to_do.do_preedit = False;
01523   a_buffer->what_to_do.do_commit = False;
01524   
01525   return True;
01526 }
01527 
01528 
01529 
01530 static Bool
01531 hangul_imebuffer_lookup_cancel_lookup (IMEBuffer a_buffer)
01532 {
01533   hangul_imebuffer_free_lookup_buffer (a_buffer->lookup_buffer, NULL);
01534   a_buffer->lookup_buffer = NULL;
01535   
01536   a_buffer->input_mode = INPUT_MODE_HANGUL;
01537   a_buffer->what_to_do.do_lookup = False;
01538   a_buffer->what_to_do.do_preedit = True;
01539 }
01540 
01541 
01542 
01543 static Bool
01544 is_printable_commit_character (IMEKeyEventStruct *iiim_key_event)
01545 {
01546   int key_code;
01547   
01548   key_code = iiim_key_event->key_code;
01549   
01550   switch (key_code){
01551   case IM_VK_ENTER:
01552   case IM_VK_TAB:
01553   case IM_VK_COMMA:
01554   case IM_VK_SPACE:
01555   case IM_VK_MINUS:
01556   case IM_VK_PERIOD:
01557   case IM_VK_SLASH:
01558   case IM_VK_0:
01559   case IM_VK_1:
01560   case IM_VK_2:
01561   case IM_VK_3:
01562   case IM_VK_4:
01563   case IM_VK_5:
01564   case IM_VK_6:
01565   case IM_VK_7:
01566   case IM_VK_8:
01567   case IM_VK_9:
01568   case IM_VK_SEMICOLON:
01569   case IM_VK_EQUALS:
01570   case IM_VK_OPEN_BRACKET:
01571   case IM_VK_BACK_SLASH:
01572   case IM_VK_CLOSE_BRACKET:
01573   case IM_VK_NUMPAD0:
01574   case IM_VK_NUMPAD1:
01575   case IM_VK_NUMPAD2:
01576   case IM_VK_NUMPAD3:
01577   case IM_VK_NUMPAD4:
01578   case IM_VK_NUMPAD5:
01579   case IM_VK_NUMPAD6:
01580   case IM_VK_NUMPAD7:
01581   case IM_VK_NUMPAD8:
01582   case IM_VK_NUMPAD9:
01583   case IM_VK_MULTIPLY:
01584   case IM_VK_ADD:
01585   case IM_VK_SEPARATER:
01586   case IM_VK_SUBTRACT:
01587   case IM_VK_DECIMAL:
01588   case IM_VK_DIVIDE:
01589   case IM_VK_BACK_QUOTE:
01590   case IM_VK_QUOTE:
01591   case IM_VK_AMPERSAND:
01592   case IM_VK_ASTERISK:
01593   case IM_VK_QUOTEDBL:
01594   case IM_VK_LESS:
01595   case IM_VK_GREATER:
01596   case IM_VK_BRACELEFT:
01597   case IM_VK_BRACERIGHT:
01598   case IM_VK_AT:
01599   case IM_VK_COLON:
01600   case IM_VK_CIRCUMFLEX:
01601   case IM_VK_DOLLAR:
01602   case IM_VK_EURO_SIGN:
01603   case IM_VK_EXCLAMATION_MARK:
01604   case IM_VK_INVERTED_EXCLAMATION_MARK:
01605   case IM_VK_LEFT_PARENTHESIS:
01606   case IM_VK_NUMBER_SIGN:
01607   case IM_VK_PLUS:
01608   case IM_VK_RIGHT_PARENTHESIS:
01609   case IM_VK_UNDERSCORE:
01610   case IM_VK_DEAD_TILDE:
01611   case 0x7e: /* Tilde.. */
01612     return True;
01613     break;
01614   default:
01615     return False;
01616     break;
01617   }
01618 
01619 }
01620 
01621 static Bool
01622 u16_to_ko_euc (UTFCHAR *u16str, unsigned char **euc_return)
01623 {
01624   iconv_t cd;
01625   size_t ret;
01626   char inbuffer[256], outbuffer[256];
01627   char *inptr;
01628   char *outptr;
01629   int utflen;
01630   int inlen, outlen;
01631   
01632   assert (u16str != NULL);
01633 
01634   if  (u16str == NULL){
01635     fprintf (stderr,
01636             "u16_to_ko_euc error: u16str is NULL\n");
01637     return False;
01638   }
01639 #if 0
01640   inbuffer = (unsigned char *) calloc (2 * (_utfchar_length (u16str) + 1), 1);
01641 #endif
01642   utflen = _utfchar_length (u16str);
01643   memset (inbuffer, 0, sizeof (inbuffer));
01644   memset (outbuffer, 0, sizeof (outbuffer));
01645   memcpy (inbuffer, u16str, sizeof (UTFCHAR ) * (utflen + 1));
01646   inptr = inbuffer;
01647   inlen = sizeof (UTFCHAR ) * utflen;
01648   
01649 #if 0
01650   inlen = 2 * (_utfchar_length (u16str) + 1);
01651   outbuffer = (unsigned char *) calloc (2 * (_utfchar_length (u16str) + 1), 1);
01652 #endif
01653   
01654   outptr = outbuffer;
01655   outlen = sizeof (outbuffer);
01656   
01657   cd = iconv_open ("EUC-KR", "UTF16");
01658   if (cd == (iconv_t) -1) {
01659     fprintf (stderr, "u16_to_ko_euc: iconv_open error\n");
01660     return False;
01661   }
01662   
01663   ret = iconv (cd,
01664               (const char **)&inptr, &inlen,
01665               (char **)&outptr, &outlen);
01666   
01667   if (ret == (size_t) -1){
01668     fprintf (stderr, "u16_to_ko_euc error: iconv error\n");
01669     if ((iconv_t)cd)
01670       iconv_close (cd);
01671     
01672     return False;
01673     
01674   } else {
01675     
01676     if (euc_return){
01677       memcpy (*euc_return, outbuffer,
01678              2 * (_utfchar_length (u16str) + 1) - outlen);
01679       *(*euc_return + (2 * (_utfchar_length (u16str) + 1) - outlen + 1)) = '\0';
01680     }
01681     iconv_close (cd);
01682     return True;
01683   }
01684 }
01685 
01686 static Bool
01687 do_search_candidates (IMEBuffer imebuffer)
01688 {
01689   int n_candidates;
01690   UTFCHAR **candidate_list;
01691   
01692   int n_result;
01693   UTFCHAR **result_list;
01694   LookupBufferStruct **lub;  
01695   Bool mthd_return;
01696   int i;
01697   HANGULBuffer *hangul_buffer = &imebuffer->composer_buffer;
01698   lub = &(imebuffer->lookup_buffer);
01699   mthd_return = composer_hangul_hanja_lookup_start (hangul_buffer,
01700                                               &n_candidates,
01701                                               &candidate_list);
01702   if ((mthd_return == False) || (n_candidates == 0)){
01703     return False;
01704   } else {
01705     if (imebuffer->config.charset == IN_UNICODE){
01706       *lub = 
01707        hangul_lookupbuf_new (n_candidates,
01708                            default_number_of_item_per_lookup_page,
01709                            candidate_list);
01710       
01711       for (i = 0 ; i < n_candidates; i++)
01712        free (candidate_list[i]);
01713       free (candidate_list);
01714       
01715       imebuffer->input_mode = INPUT_MODE_HANJA;
01716       imebuffer->what_to_do.do_lookup = True;
01717       imebuffer->what_to_do.do_preedit = True;
01718            
01719       return True;
01720     } else { /* I need to return euc candidates only */
01721 
01722       result_list = NULL;
01723       for (i = 0, n_result = 0 ; i < n_candidates; i++){
01724        if (u16_to_ko_euc (candidate_list[i],NULL)){
01725          n_result++;
01726          result_list = realloc (result_list, sizeof (UTFCHAR *) * n_result);
01727          result_list[n_result - 1] = _utfchar_dup (candidate_list [i]);
01728        }
01729       }
01730 
01731       if (!n_result)
01732        return False;
01733       *lub = 
01734        hangul_lookupbuf_new (n_result,
01735                            default_number_of_item_per_lookup_page,
01736                            result_list);
01737 
01738       for (i = 0 ; i < n_candidates; i++)
01739        free (candidate_list[i]);
01740       free (candidate_list);
01741 
01742       for (i = 0; i < n_result; i++)
01743        free (result_list[i]);
01744       free (result_list);
01745       return True;
01746     }
01747   }
01748 }
01749 
01750 /* these methods are not meant to be called from inside */
01751 
01752 static INPUT_COMMAND_TYPE_H
01753 hangul_buffer_get_keyevent_type (IMEBuffer a_buffer, IMEKeyEventStruct *key_event)
01754 {
01755   int keycode, keystatus, keychar;
01756   INPUT_MODE_T input_mode;
01757   Bool method_result;
01758   UTFCHAR *ubuf;
01759 
01760   assert (a_buffer != NULL);
01761 
01762   keycode = key_event->key_code;
01763   keychar = key_event->key_char;
01764   keystatus = key_event->key_modifier;
01765 
01766   input_mode = a_buffer->input_mode;
01767 
01768   KOLE_LOG (LOGDEST_STDOUT, "keycode: %d, keychar: %d, status: %d\n",
01769        keycode, keychar, keystatus);
01770 
01771   if (keystatus == IM_CTRL_MASK && keycode == IM_VK_SPACE){
01772     switch (a_buffer->input_mode){
01773     case INPUT_MODE_HANGUL:
01774       return INPUT_COMMAND_TURN_OFF_CONVERSION;
01775       break;
01776     case INPUT_MODE_ENGLISH:
01777       return INPUT_COMMAND_TURN_ON_CONVERSION;
01778       break;
01779     default:
01780       return INPUT_COMMAND_TURN_OFF_CONVERSION;
01781     }
01782   }
01783   if (input_mode == INPUT_MODE_HANGUL){
01784     switch (keycode){
01785 
01786     case IM_VK_ENTER:
01787     case IM_VK_TAB:
01788       return INPUT_COMMAND_COMMIT;
01789       break;
01790       
01791     case IM_VK_SPACE:
01792       if (keystatus & IM_SHIFT_MASK)
01793        return INPUT_COMMAND_TOGGLE_FULL_HALF_WIDTH;
01794       else
01795        return INPUT_COMMAND_COMMIT;
01796       break;
01797       
01798     case IM_VK_F2:
01799       if (keystatus & IM_SHIFT_MASK)
01800        return INPUT_COMMAND_SWITCH_KEYBOARD_LAYOUT;
01801       else
01802        return INPUT_COMMAND_IGNORE;
01803       break;
01804     case IM_VK_F3:
01805       if (keystatus & IM_SHIFT_MASK)
01806        return INPUT_COMMAND_SWITCH_COMMIT_METHOD;
01807       else
01808        return INPUT_COMMAND_IGNORE;
01809       break;
01810       
01811     case IM_VK_F7:
01812       if (keystatus & IM_SHIFT_MASK)
01813        return INPUT_COMMAND_SWITCH_CODESET;
01814       else
01815        return INPUT_COMMAND_IGNORE;
01816       break;
01817       
01818     case IM_VK_F8:
01819       return INPUT_COMMAND_SYMBOL_MENU_LOOKUP;
01820       break;
01821       
01822     case IM_VK_F9:
01823       if (keystatus & IM_SHIFT_MASK)
01824        return INPUT_COMMAND_HANJA_DO_LOOKUP;
01825       else
01826        return INPUT_COMMAND_IGNORE;
01827       break;
01828       
01829     case 25: /* no hanja keycode defination in SunIM.h, so hard code here, this keycode is same with IM_VK_KANJI */
01830        return INPUT_COMMAND_HANJA_DO_LOOKUP;
01831 
01832 
01833     case IM_VK_F1:
01834     case IM_VK_F4:  case IM_VK_F5:  case IM_VK_F6:
01835     case IM_VK_F10: case IM_VK_F11: case IM_VK_F12:
01836       return INPUT_COMMAND_IGNORE;
01837       break;
01838 
01839     case IM_VK_LEFT:
01840     case IM_VK_UP:
01841     case IM_VK_RIGHT:
01842     case IM_VK_DOWN:
01843     case IM_VK_PAGE_DOWN:
01844     case IM_VK_PAGE_UP:
01845     case IM_VK_HOME:
01846     case IM_VK_END:
01847       if (hangul_imebuffer_get_preedit (a_buffer, &ubuf))
01848        {
01849          if (ubuf == NULL)
01850            return INPUT_COMMAND_NOTHING;
01851          else
01852            return INPUT_COMMAND_COMMIT;
01853        }
01854       break;
01855       
01856     default:
01857       return INPUT_COMMAND_REGULAR_HANGUL;
01858       break;
01859     }
01860   } else if (input_mode == INPUT_MODE_HANJA) {
01861     switch (keycode){
01862     case IM_VK_PAGE_DOWN:
01863       return INPUT_COMMAND_LOOKUP_DO_NEXT_PAGE;
01864     case IM_VK_PAGE_UP:
01865       return INPUT_COMMAND_LOOKUP_DO_PREVIOUS_PAGE;
01866     case IM_VK_SPACE:
01867       return INPUT_COMMAND_LOOKUP_DO_SCROLL;
01868     case IM_VK_ENTER:
01869       return INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE;
01870     case IM_VK_0: case IM_VK_1: case IM_VK_2:
01871     case IM_VK_3: case IM_VK_4: case IM_VK_5:
01872     case IM_VK_6: case IM_VK_7: case IM_VK_8:
01873     case IM_VK_9:
01874       method_result = hangul_buffer_lookup_selection_is_valid (a_buffer, key_event);
01875       if (method_result == True)
01876        return INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE;
01877       else
01878        return INPUT_COMMAND_NOTHING;
01879     case IM_VK_BACK_SPACE:
01880     case IM_VK_ESCAPE:
01881       return INPUT_COMMAND_CANCEL_LOOKUP;
01882       break;
01883     default:
01884       return INPUT_COMMAND_IGNORE;
01885     }
01886   } else if (input_mode == INPUT_MODE_SYMBOL_MENU){
01887     
01888     switch (keycode) {
01889     case IM_VK_PAGE_DOWN:
01890       return INPUT_COMMAND_LOOKUP_DO_NEXT_PAGE;
01891     case IM_VK_PAGE_UP:
01892       return INPUT_COMMAND_LOOKUP_DO_PREVIOUS_PAGE;
01893     case IM_VK_SPACE:
01894       return INPUT_COMMAND_LOOKUP_DO_SCROLL;
01895     case IM_VK_ENTER:
01896       return INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE;
01897     case IM_VK_0: case IM_VK_1: case IM_VK_2:
01898     case IM_VK_3: case IM_VK_4: case IM_VK_5:
01899     case IM_VK_6: case IM_VK_7: case IM_VK_8:
01900     
01901       method_result =
01902        hangul_buffer_lookup_selection_is_valid (a_buffer, key_event);
01903       if (method_result == True)
01904        return INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE;
01905       else
01906        return INPUT_COMMAND_NOTHING;
01907     case IM_VK_BACK_SPACE:
01908     case IM_VK_ESCAPE:
01909       return INPUT_COMMAND_CANCEL_LOOKUP;
01910       break;
01911     default:
01912       return INPUT_COMMAND_NOTHING;
01913 
01914     }
01915   } else if (input_mode == INPUT_MODE_SYMBOL){
01916     switch (keycode) {
01917     case IM_VK_PAGE_DOWN:
01918       return INPUT_COMMAND_LOOKUP_DO_NEXT_PAGE;
01919     case IM_VK_PAGE_UP:
01920       return INPUT_COMMAND_LOOKUP_DO_PREVIOUS_PAGE;
01921     case IM_VK_SPACE:
01922       return INPUT_COMMAND_LOOKUP_DO_SCROLL;
01923     case IM_VK_ENTER:
01924       return INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE;
01925     case IM_VK_0: case IM_VK_1: case IM_VK_2:
01926     case IM_VK_3: case IM_VK_4: case IM_VK_5:
01927     case IM_VK_6: case IM_VK_7: case IM_VK_8:
01928     case IM_VK_9:
01929     
01930       method_result =
01931        hangul_buffer_lookup_selection_is_valid (a_buffer, key_event);
01932       if (method_result == True)
01933        return INPUT_COMMAND_LOOKUP_SELECT_CANDIDATE;
01934       else
01935        return INPUT_COMMAND_NOTHING;
01936     case IM_VK_BACK_SPACE:
01937     case IM_VK_ESCAPE:
01938       return INPUT_COMMAND_CANCEL_LOOKUP;
01939       break;
01940     default:
01941       return INPUT_COMMAND_NOTHING;
01942 
01943     }
01944   }
01945   return INPUT_COMMAND_NOTHING;
01946 }
01947 
01948 static Bool
01949 hangul_buffer_lookup_selection_is_valid (IMEBuffer a_buffer,
01950                                     IMEKeyEventStruct *key_event)
01951 {
01952   LookupBufferStruct *lub;
01953   Bool method_result;
01954   int n_count;
01955 
01956   assert (a_buffer != NULL);
01957   lub = a_buffer->lookup_buffer;
01958   n_count =
01959     hangul_lookupbuf_get_count_of_candidates_in_current_page (lub);
01960   
01961   
01962   if (n_count == -1)
01963     return False;
01964   else {
01965     if (key_event->key_code >= IM_VK_0 && 
01966        key_event->key_code < (IM_VK_0 + n_count) )
01967       return True;
01968     else
01969       return False;
01970   }
01971   return True;
01972 }
01973 
01974 static Bool
01975 hangul_imebuffer_get_configuration (IMEBuffer imebuffer, int *count, KOLE_config ***pconfig)
01976 {
01977   int i;
01978   *count = g_n_config;
01979   *pconfig = (KOLE_config **) calloc (*count, sizeof (KOLE_config *));
01980   for (i = 0; i < *count; i++)
01981     (*pconfig)[i] = leoption_copy (g_engine_config [i]);
01982   
01983   return True;
01984 }
01985 
01986 static void
01987 node_print (void *data)
01988 {
01989   HHItem *p = (HHItem *) data;
01990   hhitem_print_string (p, NULL);
01991   printf ("\n");
01992   return;
01993 }
01994 
01995 static Bool
01996 apply_kole_config_to_session (int n, KOLE_config **pconfig, Config *sconf)
01997 {
01998   int i;
01999   assert (sconf != NULL);
02000   if (sconf == NULL){
02001     fprintf (stderr,
02002             "apply_kole_config_to_session error: sconf is NULL\n");
02003     return False;
02004   }
02005   for (i = 0; i < n; i++){
02006     switch (pconfig[i]->type){
02007     case KOLE_OPTION_TYPE_KEYBOARD:
02008       sconf->keyboard = pconfig[i]->v.kbd;
02009       break;
02010     case KOLE_OPTION_TYPE_CHARSET:
02011       sconf->charset = pconfig[i]->v.cset;
02012       break;
02013     case KOLE_OPTION_TYPE_DELETION:
02014       sconf->deletion = pconfig[i]->v.del;
02015       break;
02016     case KOLE_OPTION_TYPE_CHARBASED_COMMIT:
02017       sconf->commit_mode = pconfig[i]->v.commit_by;
02018       break;
02019     }
02020   }
02021   return True;
02022 }
02023 
02024 static void
02025 hangul_engine_print_configuration ()
02026 {
02027   int i;
02028   for (i = 0; i < g_n_config; i++){
02029     leoption_debug_print (g_engine_config[i]);
02030   }
02031 }
02032 
02033 
02034 
02035 static void
02036 hangul_buffer_debug_print (IMEBuffer a_buffer)
02037 {
02038   printf ("session id: %d\n", a_buffer->session_id);
02039   printf ("engine  id :%d\n", a_buffer->engine_id);
02040   if(a_buffer->commit_string)
02041          printf ("commit_string is %s.\n", a_buffer->commit_string);
02042 
02043   /*if(a_buffer->composer_buffer.buffer)
02044   printf ("length of composer_buffer is %d\n", a_buffer->composer_buffer.count);*/
02045 
02046   if(a_buffer->lookup_buffer)
02047          printf ("num of candidat is %d.\n", a_buffer->lookup_buffer->n_candidates);
02048   printf ("waht_to do is %d.\n", a_buffer->what_to_do);
02049   printf ("Config: charset id %d, deletion is %d, keyboad type is %d, commit_mode is %d\n", \
02050          a_buffer->config.charset, a_buffer->config.deletion, a_buffer->config.keyboard, a_buffer->config.commit_mode);
02051 
02052   switch (a_buffer->input_mode){
02053   case INPUT_MODE_NONE:
02054     printf ("input mode : NONE");
02055     
02056     break;
02057   case INPUT_MODE_ENGLISH:
02058     printf ("input mode : ENGLISH");
02059     break;
02060   case INPUT_MODE_HANGUL:
02061     printf ("input mode : HANGUL");
02062     break;
02063   case INPUT_MODE_HANJA:
02064     printf ("input mode : HANJA");
02065     break;
02066   case INPUT_MODE_HEX_EUC:
02067     printf ("input mode : EUC");
02068     break;
02069   case INPUT_MODE_HEX_UTF8:
02070     printf ("input mode : UTF8");
02071     break;
02072   case INPUT_MODE_SYMBOL:
02073     printf ("input mode : SYMBOL");
02074     break;
02075   default:
02076     printf ("strange input mode value: %d\n", a_buffer->input_mode);
02077     break;
02078   }
02079 }
02080