Back to index

im-sdk  12.3.91
iiimcfFun.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2001 Sun Microsystems, Inc. All Rights Reserved.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a
00005 copy of this software and associated documentation files (the
00006 "Software"), to deal in the Software without restriction, including
00007 without limitation the rights to use, copy, modify, merge, publish,
00008 distribute, sublicense, and/or sell copies of the Software, and to
00009 permit persons to whom the Software is furnished to do so, subject to
00010 the following conditions: The above copyright notice and this
00011 permission notice shall be included in all copies or substantial
00012 portions of the Software.
00013 
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00016 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00017 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00018 IN NO EVENT SHALL THE OPEN GROUP OR SUN MICROSYSTEMS, INC. BE LIABLE
00019 FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00020 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
00021 THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF
00022 ADVISED IN ADVANCE OF THE POSSIBILITY OF SUCH DAMAGES.
00023 
00024 
00025 Except as contained in this notice, the names of The Open Group and/or
00026 Sun Microsystems, Inc. shall not be used in advertising or otherwise to
00027 promote the sale, use or other dealings in this Software without prior
00028 written authorization from The Open Group and/or Sun Microsystems,
00029 Inc., as applicable.
00030 
00031 
00032 X Window System is a trademark of The Open Group
00033 
00034 OSF/1, OSF/Motif and Motif are registered trademarks, and OSF, the OSF
00035 logo, LBX, X Window System, and Xinerama are trademarks of the Open
00036 Group. All other trademarks and registered trademarks mentioned herein
00037 are the property of their respective owners. No right, title or
00038 interest in or to any trademark, service mark, logo or trade name of
00039 Sun Microsystems, Inc. or its licensors is granted.
00040 
00041 */
00042 
00043 #include "iiimpReq.h"
00044 #include "iiimpIM.h"
00045 #include "guiIM.h"
00046 #include "XimpIm.h"
00047 #include "xiiimp.h"
00048 #include "iiimpAuth.h"
00049 #include "iiimpAuxP.h"
00050 #include "iiimpUtil.h"
00051 #include "iiimpColor.h"
00052 #include "iiimpTr.h"
00053 #include "iiimpConv.h"
00054 #include "iiimpSwitcher.h"
00055 #include "KeyMap.h"
00056 #include "trace_message.h"
00057 #include <stdio.h>
00058 #include <locale.h>
00059 #include <string.h>
00060 #include <sys/utsname.h>
00061 #include <iiimcf.h>
00062 #include <langinfo.h>
00063 #include <limits.h>
00064 #include <values.h>
00065 #include <iconv.h>
00066 #include <X11/Xlib.h>
00067 #include <X11/Xatom.h>
00068 
00069 static IIIMCF_language get_input_language (XicCommon ic, char *input_language,
00070                                       Bool exact_match);
00071 
00072 static IIIMF_status
00073 process_keyevent(
00074     XicCommon ic,
00075     IIIMCF_event ev
00076 )
00077 {
00078     IIIMF_status st;
00079     IIIMCF_keyevent kev;
00080     XKeyEvent xkev;
00081     XimCommon im = (XimCommon)ic->core.im;
00082 
00083     st = iiimcf_get_keyevent_value(ev, &kev);
00084     if (st != IIIMF_STATUS_SUCCESS) return st;
00085 
00086     IIIMCF_keyevent_To_XKeyEvent(&kev, im->core.display, ic->core.focus_window, &xkev);
00087     
00088     if (ic->forward_event_callback.callback) {
00089        ic->forward_event_callback.callback((XIC)ic,
00090                                        ic->forward_event_callback.client_data,
00091                                        (XPointer)&xkev);
00092     } else {
00093        HoldXKeyEvent(ic, (XEvent*)&xkev);
00094     }
00095 
00096     return IIIMF_STATUS_SUCCESS;
00097 }
00098 
00099 static IIIMF_status
00100 process_trigger_notify(
00101     XicCommon ic,
00102     IIIMCF_event ev
00103 )
00104 {
00105     IIIMF_status st;
00106     int flag;
00107 
00108     st = iiimcf_get_trigger_notify_flag(ev, &flag);
00109     if (st != IIIMF_STATUS_SUCCESS) return st;
00110     if (flag)
00111        SetConversionMode(ic, True);
00112     else
00113        SetConversionMode(ic, False);
00114 
00115     return IIIMF_STATUS_SUCCESS;
00116 }
00117     
00118 static IIIMF_status
00119 draw_preedit(
00120     XicCommon ic
00121 )
00122 {
00123     IIIMF_status st;
00124     IIIMCF_text text;
00125     XIMText cbtext;
00126     int caret = 0, len;
00127     IMFeedbackList *feedback_list = NULL;
00128     XICCallback *cb = &ic->core.preedit_attr.draw_callback;
00129     XIMPreeditDrawCallbackStruct call_data;
00130     XimCommon im = (XimCommon)ic->core.im;
00131     Bool useUnicode;
00132 
00133     memset(&call_data, 0, sizeof(XIMPreeditDrawCallbackStruct));
00134     memset(&cbtext, 0, sizeof(XIMText));
00135 
00136     useUnicode = (XIM_USE_UNICODE(im) && cb->callback &&
00137                 (ic->core.input_style & XIMPreeditCallbacks));
00138 
00139     st = iiimcf_get_preedit_text(XIC_IIIMP(ic, context), &text, &caret);
00140     if (st == IIIMF_STATUS_NO_PREEDIT) {
00141        call_data.text = NULL;
00142        len = 0;
00143     } else {
00144        if (st != IIIMF_STATUS_SUCCESS) return st;
00145        st = iiimcf_get_text_length(text, &len);
00146        if (st != IIIMF_STATUS_SUCCESS) return st;
00147        if (len > 0) {
00148            st = IIimpConvertToXIMText(text, &cbtext, &feedback_list, useUnicode);
00149            if (st != IIIMF_STATUS_SUCCESS) return st;
00150            call_data.text = &cbtext;
00151        } else {
00152            call_data.text = NULL;
00153        }
00154     }
00155     call_data.caret = caret;
00156     call_data.chg_first = 0;
00157     call_data.chg_length = XIC_IIIMP(ic, preedit_prev_len);
00158     CallPreeditDrawCallback(ic, &call_data, feedback_list);
00159     FreeFeedbackList(feedback_list, cbtext.length);
00160     XIC_IIIMP(ic, preedit_prev_len) = len;
00161     if (cbtext.string.multi_byte) Xfree(cbtext.string.multi_byte);
00162     if (cbtext.feedback) Xfree(cbtext.feedback);
00163 
00164     return IIIMF_STATUS_SUCCESS;
00165 }
00166 
00167 static IIIMF_status
00168 draw_status(
00169     XicCommon ic
00170 )
00171 {
00172     IIIMF_status st;
00173     IIIMCF_text text;
00174     XIMText cbtext;
00175     IMFeedbackList *feedback_list = NULL;
00176     XICCallback *cb = &ic->core.status_attr.draw_callback;
00177     XIMStatusDrawCallbackStruct call_data;
00178     XimCommon im = (XimCommon)ic->core.im;
00179     Bool useUnicode;
00180 
00181     memset(&call_data, 0, sizeof(XIMStatusDrawCallbackStruct));
00182     memset(&cbtext, 0, sizeof(XIMText));
00183 
00184     useUnicode = (XIM_USE_UNICODE(im) && cb->callback &&
00185                 (ic->core.input_style & XIMStatusCallbacks));
00186 
00187     st = iiimcf_get_status_text(XIC_IIIMP(ic, context), &text);
00188     if (st == IIIMF_STATUS_NO_STATUS_TEXT) {
00189        /* erase status text.  */
00190        cbtext.feedback = NULL;
00191        cbtext.string.multi_byte = NULL;
00192        cbtext.length = 0;
00193        call_data.data.text = &cbtext;
00194     } else {
00195        if (st != IIIMF_STATUS_SUCCESS) return st;
00196        st = IIimpConvertToXIMText(text, &cbtext, &feedback_list, useUnicode);
00197        if (st != IIIMF_STATUS_SUCCESS) return st;
00198        call_data.data.text = &cbtext;
00199        call_data.type = XIMTextType;
00200     }
00201     CallStatusDrawCallback(ic, &call_data, feedback_list);
00202     FreeFeedbackList(feedback_list, cbtext.length);
00203     if (cbtext.string.multi_byte) Xfree(cbtext.string.multi_byte);
00204     if (cbtext.feedback) Xfree(cbtext.feedback);
00205 
00206     return IIIMF_STATUS_SUCCESS;
00207 }
00208 
00209 static IIIMF_status
00210 start_lookup_choice(
00211     XicCommon ic
00212 )
00213 {
00214     IIIMF_status st;
00215     IIIMCF_lookup_choice lc;
00216     XIMLookupStartCallbackStruct2 call_data;
00217     int direction;
00218 
00219     st = iiimcf_get_lookup_choice(XIC_IIIMP(ic, context), &lc);
00220     if (st != IIIMF_STATUS_SUCCESS) return st;
00221     st = iiimcf_get_lookup_choice_configuration(lc,
00222                                           &call_data.choice_per_window,
00223                                           &call_data.nrows,
00224                                           &call_data.ncolumns,
00225                                           &direction);
00226     if (direction == IIIMCF_LOOKUP_CHOICE_HORIZONTAL_DIRECTION) {
00227        call_data.draw_up_direction = XIMDrawUpHorizontally;
00228     } else {
00229        call_data.draw_up_direction = XIMDrawUpVertically;
00230     }
00231     if (st != IIIMF_STATUS_SUCCESS) return st;
00232     /* libiiimcf rules them.  */
00233     call_data.which_is_master = IM_LOOKUP_CHOICE_START_SERVER_IS_MASTER;
00234     call_data.who_owns_label = 0;
00235 
00236     if (ic->lookup_start_callback.callback) {
00237        XIMCallback *cb = &ic->lookup_start_callback;
00238        (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&call_data);
00239     } else {
00240        XIC_GUI(ic, change_lookup)((XIC)ic, LOOKUP_START,
00241                                (XPointer)&call_data);
00242     }
00243 
00244     return IIIMF_STATUS_SUCCESS;
00245 }
00246 
00247 static IIIMF_status
00248 draw_lookup_choice(
00249     XicCommon ic
00250 )
00251 {
00252     IIIMF_status st;
00253     IIIMCF_lookup_choice lc;
00254     IIIMCF_text title, label, cand;
00255     XIMLookupDrawCallbackStruct2 call_data;
00256     XIMChoiceObject2 choice_object;
00257     XIMText *choice_list = (XIMText*)NULL, *label_list = (XIMText*)NULL;
00258     XIMText title_text;
00259     IMFeedbackList **choice_feedback = (IMFeedbackList**)NULL;
00260     IMFeedbackList **label_feedback = (IMFeedbackList**)NULL;
00261     XimCommon im = (XimCommon)ic->core.im;
00262     Bool useUnicode;
00263     int size, flag;
00264     int i;
00265 
00266     st = iiimcf_get_lookup_choice(XIC_IIIMP(ic, context), &lc);
00267     if (st != IIIMF_STATUS_SUCCESS) return st;
00268     st = iiimcf_get_lookup_choice_size(lc, &size,
00269                                    &call_data.first_index,
00270                                    &call_data.last_index,
00271                                    &call_data.current_index);
00272     if (st != IIIMF_STATUS_SUCCESS) return st;
00273     if (size <= 0) return IIIMF_STATUS_SUCCESS;
00274     st = iiimcf_get_lookup_choice_title(lc, &title);
00275     if (st != IIIMF_STATUS_SUCCESS) return st;
00276 
00277     useUnicode = (XIM_USE_UNICODE(im) &&
00278                 ic->lookup_draw_callback.callback);
00279 
00280     choice_list = (XIMText*) Xmalloc(sizeof(XIMText) * size * 2);
00281     if (!choice_list) {
00282        st = IIIMF_STATUS_MALLOC;
00283        goto cleanup;
00284     }
00285     memset(choice_list, 0, sizeof(XIMText) * size * 2);
00286     label_list = choice_list + size;
00287 
00288     choice_feedback = (IMFeedbackList**) Xmalloc(sizeof(IMFeedbackList*) * size * 2);
00289     if (!choice_feedback) {
00290        st = IIIMF_STATUS_MALLOC;
00291        goto cleanup;
00292     }
00293     memset(choice_feedback, 0, sizeof(IMFeedbackList*) * size * 2);
00294     label_feedback = choice_feedback + size;
00295 
00296     memset(&title_text, 0, sizeof(XIMText));
00297     st = IIimpConvertToXIMText(title, &title_text, NULL, useUnicode);
00298     if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00299 
00300     for (i = 0; i < size; i++) {
00301        st = iiimcf_get_lookup_choice_item(lc, i, &cand, &label, &flag);
00302        if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00303        st = IIimpConvertToXIMText(cand, &choice_list[i],
00304                                &choice_feedback[i], useUnicode);
00305        if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00306        st = IIimpConvertToXIMText(label, &label_list[i],
00307                                &label_feedback[i], useUnicode);
00308        if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00309     }
00310 
00311     call_data.n_choices = size;
00312     choice_object.label_decoration = NO_DECORATION;
00313     choice_object.value = choice_list;
00314     choice_object.label = label_list;
00315     choice_object.value_feedback = choice_feedback;
00316     choice_object.label_feedback = label_feedback;
00317     call_data.choices = &choice_object;
00318     call_data.title = &title_text;
00319 
00320     if (ic->lookup_draw_callback.callback) {
00321        XIMCallback *cb = &ic->lookup_draw_callback;
00322        (*cb->callback)((XIC)ic, cb->client_data, (XPointer)&call_data);
00323     } else {
00324        XIC_GUI(ic, change_lookup)((XIC)ic, LOOKUP_DRAW,
00325                                (XPointer)&call_data);
00326     }
00327 
00328 cleanup:
00329 
00330     for (i = 0; i < size; i++) {
00331        if (choice_list) {
00332            if (choice_feedback) {
00333               FreeFeedbackList(choice_feedback[i], choice_list[i].length);
00334            }
00335            if (choice_list[i].string.multi_byte) {
00336               Xfree(choice_list[i].string.multi_byte);
00337            }
00338            if (choice_list[i].feedback) {
00339               Xfree(choice_list[i].feedback);
00340            }
00341        }
00342        if (label_list) {
00343            if (label_feedback) {
00344               FreeFeedbackList(label_feedback[i], label_list[i].length);
00345            }
00346            if (label_list[i].string.multi_byte) {
00347               Xfree(label_list[i].string.multi_byte);
00348            }
00349            if (label_list[i].feedback) {
00350               Xfree(label_list[i].feedback);
00351            }
00352        }
00353     }
00354     if (choice_list) Xfree(choice_list);
00355     if (choice_feedback) Xfree(choice_feedback);
00356 
00357     if (title_text.string.multi_byte) {
00358        Xfree(title_text.string.multi_byte);
00359     }
00360     if (title_text.feedback) {
00361        Xfree(title_text.feedback);
00362     }
00363 
00364     return st;
00365 }
00366 
00367 static IIIMF_status
00368 end_lookup_choice(
00369     XicCommon ic
00370 )
00371 {
00372     if (ic->lookup_done_callback.callback) {
00373        XIMCallback *cb = &ic->lookup_done_callback;
00374        (*cb->callback)((XIC)ic, cb->client_data, (XPointer)NULL);
00375     } else {
00376        XIC_GUI(ic, change_lookup)((XIC)ic, LOOKUP_DONE, (XPointer)NULL);
00377     }
00378 
00379     return IIIMF_STATUS_SUCCESS;
00380 }
00381 
00382 static IIIMF_status
00383 commit(
00384     XicCommon ic
00385 )
00386 {
00387     IIIMF_status st;
00388     IIIMCF_text text;
00389     XEvent ev;
00390     Bool useUnicode;
00391     XimCommon im = (XimCommon)ic->core.im;
00392 
00393     useUnicode = (XIM_USE_UNICODE(im) &&
00394                 ic->commit_string_callback.callback);
00395 
00396     /* private XIC extension */
00397     if (ic->commit_string_callback.callback) {
00398        XIMText cbtext;
00399        XIMCallback *cb = &ic->commit_string_callback;
00400        int len = 0;
00401 
00402        st = iiimcf_get_committed_text(XIC_IIIMP(ic, context), &text);
00403        if (st != IIIMF_STATUS_SUCCESS) return st;
00404        st = iiimcf_get_text_length(text, &len);
00405        if (st != IIIMF_STATUS_SUCCESS) return st;
00406        st = IIimpConvertToXIMText(text, &cbtext, NULL, useUnicode);
00407        if (st != IIIMF_STATUS_SUCCESS) return st;
00408        if (ic->core.input_style & XIMPreeditCallbacks) {
00409          /* erace preedit text */
00410          XIMPreeditDrawCallbackStruct call_data;
00411          memset(&call_data, 0, sizeof(XIMPreeditDrawCallbackStruct));
00412          call_data.caret = len;
00413          call_data.chg_length = len;
00414          CallPreeditDrawCallback(ic, &call_data, NULL);
00415          XIC_IIIMP(ic, preedit_prev_len) = 0;
00416        }
00417        (*cb->callback)((XIC)ic,
00418                      cb->client_data,
00419                      (XPointer)&cbtext);  /* for UNICODE1 */
00420        /* no need to fake a keyevent to be putback */
00421        if (cbtext.string.multi_byte) Xfree(cbtext.string.multi_byte);
00422        if (cbtext.feedback) Xfree(cbtext.feedback);
00423        return IIIMF_STATUS_SUCCESS;
00424     }
00425 
00426     /* fake a key press event */
00427     memset(&ev, 0, sizeof(ev));
00428     ev.type = (int)KeyPress;
00429     ev.xkey.display = im->core.display;
00430     ev.xkey.window = ic->core.focus_window;
00431     ev.xkey.root = None;
00432     ev.xkey.subwindow = None;
00433     ev.xkey.keycode = XIM_COMPOSE_KEYCODE;
00434     ev.xkey.same_screen = True;
00435     /* XPutBackEvent(im->core.display, &ev); */
00436     /* ic->ximp_icpart->putback_key_event = True; */
00437     HoldXKeyEvent(ic, &ev);
00438     XIC_IIIMP(ic, keysym_return) = NoSymbol;
00439     XIC_IIIMP(ic, has_keyevent_return) = False;
00440     XIC_IIIMP(ic, committed_text_consumed) = False;
00441 
00442     return IIIMF_STATUS_SUCCESS;
00443 }
00444 
00445 IIIMF_status
00446 IMProcessIncomingEvent(
00447     XicCommon ic
00448 )
00449 {
00450     IIIMF_status st;
00451     IIIMCF_event ev;
00452     IIIMCF_event_type et;
00453     IIIMCF_context c;
00454 
00455     if (!ic) return IIIMF_STATUS_SUCCESS;
00456 
00457     c = XIC_IIIMP(ic, context);
00458     while ((st = iiimcf_get_next_event(c, &ev))
00459           == IIIMF_STATUS_SUCCESS) {
00460        st = iiimcf_dispatch_event(c, ev);
00461        if (st != IIIMF_STATUS_SUCCESS) {
00462            if (iiimcf_get_event_type(ev, &et) != IIIMF_STATUS_SUCCESS)
00463               continue;
00464            switch (et) {
00465              case IIIMCF_EVENT_TYPE_KEYEVENT:
00466               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_KEYEVENT\n"));
00467               process_keyevent(ic, ev);
00468               break;
00469 
00470              case IIIMCF_EVENT_TYPE_TRIGGER_NOTIFY:
00471               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_TRIGGER_NOTIFY\n"));
00472               process_trigger_notify(ic, ev);
00473               ic_switcher_set_conversion_mode (ic);
00474               break;
00475 
00476              case IIIMCF_EVENT_TYPE_UI_PREEDIT_START:
00477               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_PREEDIT_START\n"));
00478               CallPreeditStartCallback(ic, NULL);
00479               break;
00480              case IIIMCF_EVENT_TYPE_UI_PREEDIT_CHANGE:
00481               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_PREEDIT_CHANGE\n"));
00482               draw_preedit(ic);
00483               break;
00484              case IIIMCF_EVENT_TYPE_UI_PREEDIT_DONE:
00485               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_PREEDIT_DONE\n"));
00486               CallPreeditDoneCallback(ic, NULL);
00487               break;
00488 
00489              case IIIMCF_EVENT_TYPE_UI_STATUS_START:
00490               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_STATUS_START\n"));
00491               CallStatusStartCallback(ic, NULL);
00492               break;
00493              case IIIMCF_EVENT_TYPE_UI_STATUS_CHANGE:
00494               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_STATUS_CHANGE\n"));
00495               draw_status(ic);
00496               break;
00497              case IIIMCF_EVENT_TYPE_UI_STATUS_DONE:
00498               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_STATUS_DONE\n"));
00499               CallStatusDoneCallback(ic, NULL);
00500               break;
00501 
00502              case IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_START:
00503               start_lookup_choice(ic);
00504               break;
00505              case IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_CHANGE:
00506               draw_lookup_choice(ic);
00507               break;
00508              case IIIMCF_EVENT_TYPE_UI_LOOKUP_CHOICE_DONE:
00509               end_lookup_choice(ic);
00510               break;
00511 
00512              case IIIMCF_EVENT_TYPE_AUX_START:
00513               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_AUX_START\n"));
00514               IIimpAuxStart(ic, ev);
00515               break;
00516              case IIIMCF_EVENT_TYPE_AUX_DRAW:
00517               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_AUX_DRAW\n"));
00518               IIimpAuxDraw(ic, ev);
00519               break;
00520              case IIIMCF_EVENT_TYPE_AUX_DONE:
00521               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_AUX_DONE\n"));
00522               IIimpAuxDone(ic, ev);
00523               break;
00524 
00525              case IIIMCF_EVENT_TYPE_AUX_GETVALUES:
00526               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_AUX_GETVALUES\n"));
00527               IIimpAuxGetValuesReply(ic, ev);
00528               break;
00529              case IIIMCF_EVENT_TYPE_UI_COMMIT:
00530               TRACE_MESSAGE('i', ("IIIMCF_EVENT_TYPE_UI_COMMIT\n"));
00531               commit(ic);
00532               break;
00533              default:
00534               TRACE_MESSAGE('i', ("unhandled IIIMCF_EVENT_TYPE\n"));
00535               break;
00536            }
00537            /* discard event */
00538            iiimcf_ignore_event(ev);
00539        }
00540     }
00541 
00542     PutBackXKeyEvent(ic);
00543 
00544     return IIIMF_STATUS_SUCCESS;
00545 }
00546 
00547 Bool
00548 IMTriggerNotify(
00549     XicCommon ic,
00550     XICConversionMode conv_mode
00551 )
00552 {
00553     IIIMCF_event ev;
00554     if (!ic) return False;
00555 
00556     if (conv_mode == CONV_OFF) {
00557       end_lookup_choice(ic);
00558     }
00559 
00560     if (iiimcf_create_trigger_notify_event(conv_mode, &ev)
00561        != IIIMF_STATUS_SUCCESS) return False;
00562 
00563     if (iiimcf_forward_event(XIC_IIIMP(ic, context), ev)
00564        != IIIMF_STATUS_SUCCESS) return False;
00565     IMProcessIncomingEvent(ic);
00566 
00567     return True;
00568 }
00569 
00570 Bool
00571 IMForwardEvent(
00572     XicCommon ic,
00573     XEvent *ev
00574 )
00575 {
00576     IIIMF_status st;
00577     IIIMCF_keyevent kev;
00578     IIIMCF_event event;
00579 
00580     if (!XKeyEvent_To_IIIMCF_keyevent((XKeyEvent*) ev, &kev))
00581        return True;
00582 
00583 #if 0 /* SHOULD BE REMOVED */
00584     fprintf(stderr, "(%d, %d)->(%d, %d, %d)\n",
00585            ev->xkey.keycode, ev->xkey.state,
00586            kev.keycode, kev.keychar, kev.modifier);
00587 #endif
00588 
00589     st = iiimcf_create_keyevent(&kev, &event);
00590     if (st != IIIMF_STATUS_SUCCESS) return False;
00591 
00592     st = iiimcf_forward_event(XIC_IIIMP(ic, context), event);
00593 
00594     IMProcessIncomingEvent(ic);
00595 
00596     if (st != IIIMF_STATUS_SUCCESS) return False;
00597 
00598     return True;
00599 }
00600 
00601 IIIMF_status
00602 IMChangeFocus(
00603     XicCommon ic,
00604     int flag
00605 )
00606 {
00607     IIIMF_status st;
00608     IIIMCF_event event;
00609 
00610     if (flag) {
00611        st = iiimcf_create_seticfocus_event(&event);
00612        IIimpAuxSetICFocus(ic);
00613     } else {
00614        st = iiimcf_create_unseticfocus_event(&event);
00615        IIimpAuxUnsetICFocus(ic);
00616     }
00617     if (st != IIIMF_STATUS_SUCCESS) return st;
00618 
00619     st = iiimcf_forward_event(XIC_IIIMP(ic, context), event);
00620     IMProcessIncomingEvent(ic);
00621 
00622     return st;
00623 }
00624 
00625 void
00626 IM_free_langlist(
00627     XimCommon im
00628 )
00629 {
00630     int i;
00631     int n = XIM_IIIMP(im, count_languages);
00632     XIMText *language_list = XIM_IIIMP(im, supported_languages);
00633     char *str;
00634 
00635     if (language_list) {
00636        for (i = 0; i < n; i++) {
00637            str = language_list[i].string.multi_byte;
00638            if (str) free(str);
00639        }
00640        free(language_list);
00641     }
00642     XIM_IIIMP(im, count_languages) = 0;
00643     XIM_IIIMP(im, supported_languages) = NULL;
00644 }
00645 
00646 static void
00647 init_langlist(
00648     XimCommon im
00649 )
00650 {
00651     int i, n, len;
00652     const char *ll;
00653     char *ll2;
00654     IIIMCF_language *plangs;
00655     XIMText *language_list = NULL;
00656 
00657     IM_free_langlist(im);
00658     if (iiimcf_get_supported_languages(XIM_IIIMP(im, handle), &n, &plangs)
00659        != IIIMF_STATUS_SUCCESS)
00660        return;
00661 
00662     language_list = (XIMText*) Xmalloc(sizeof(XIMText) * n);
00663     if (!language_list) return;
00664     memset(language_list, 0, sizeof(XIMText) * n);
00665     XIM_IIIMP(im, count_languages) = n;
00666     XIM_IIIMP(im, supported_languages) = language_list;
00667     for (i = 0; i < n; i++) {
00668        iiimcf_get_language_id(plangs[i], &ll);
00669        len = strlen(ll);
00670        ll2 = (char*) Xmalloc(sizeof(char) * (len + 1));
00671        if (!ll2) {
00672            IM_free_langlist(im);
00673            return;
00674        }
00675        memcpy(ll2, ll, sizeof(char) * (len + 1));
00676        language_list[i].length = len;
00677        language_list[i].string.multi_byte = ll2;
00678     }
00679 
00680     return;
00681 }
00682 
00683 static IIIMF_status
00684 IMSetupAuxObject(
00685     XimCommon im
00686 );
00687 
00688 IIIMF_status
00689 IMCreateHandle(
00690     XimCommon im
00691 )
00692 {
00693     IIIMF_status st;
00694     IIIMCF_attr attr;
00695     char *address, *service;
00696     Atom iiimd;
00697     Window iiimx;
00698     Atom type;
00699     int format;
00700     unsigned long length;
00701     unsigned long nitem;
00702     unsigned char *prop;
00703 
00704     address = NULL;
00705     service = NULL;
00706     prop = NULL;
00707 
00708     st = iiimcf_create_attr(&attr);
00709     if (st != IIIMF_STATUS_SUCCESS) return st;
00710     if (!XIM_IIIMP(im, client_type)) {
00711        XIM_IIIMP(im, client_type) = IIIMP_CLIENT_TYPE; /* default */
00712     }
00713     st = iiimcf_attr_put_string_value(attr, IIIMCF_ATTR_CLIENT_TYPE,
00714                                   XIM_IIIMP(im, client_type));
00715     if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00716     if (im->core.display) {
00717        Display *dpy = im->core.display;
00718 
00719        st = iiimcf_attr_put_string_value(attr, IIIMCF_ATTR_CLIENT_X_DISPLAY_NAME,
00720                                      XDisplayString(dpy));
00721        if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00722        st = iiimcf_attr_put_string_value(attr, IIIMCF_ATTR_CLIENT_X_SERVER_VENDOR,
00723                                      XServerVendor(dpy));
00724        if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00725     }
00726 
00727     if (NULL != im->core.display) {
00728        iiimd = XInternAtom (im->core.display, "IIIM_SERVER", True);
00729        if (None != iiimd) {
00730            iiimx = XGetSelectionOwner (im->core.display, iiimd);
00731        } else {
00732            iiimx = None;
00733        }
00734        if (None != iiimx) {
00735            XGetWindowProperty(im->core.display, iiimx, iiimd,
00736                             0, INT_MAX, False, XA_STRING,
00737                             &type, &format, &nitem, &length, &prop);
00738            if (NULL == prop) {
00739            } else if (0 == strncmp("uds:", (char *)prop, 4)) {
00740               address = strdup((prop + 4));
00741               service = "";
00742               if (NULL == address) goto cleanup;
00743            } else {
00744            }
00745        }
00746     }
00747     if ((NULL == address) && (im->core.im_name)) {
00748        address = strdup(im->core.im_name);
00749        if (!address) goto cleanup;
00750        service = index(address, ':');
00751        if (service) {
00752            *service = '\0';
00753            service++;
00754        }
00755     }
00756 
00757     if (NULL != address) {
00758        st = iiimcf_attr_put_string_value(attr, IIIMCF_ATTR_SERVER_ADDRESS,
00759                                      address);
00760        if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00761        if (service) {
00762            st = iiimcf_attr_put_string_value(attr, IIIMCF_ATTR_SERVER_SERVICE,
00763                                          service);
00764            if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00765        }
00766     }
00767     st = iiimcf_create_handle(attr, &XIM_IIIMP(im, handle));
00768     if (st != IIIMF_STATUS_SUCCESS) goto cleanup;
00769     init_langlist(im);
00770     RegisterTriggerKeys(im);
00771     IMSetupAuxObject(im);
00772 
00773 cleanup:
00774     iiimcf_destroy_attr(attr);
00775     if (address) free(address);
00776     if (NULL != prop) XFree(prop);
00777     return st;
00778 }
00779 
00780 IIIMF_status
00781 IMCreateIC(
00782     XimCommon im,
00783     IIIMCF_context *pc
00784 )
00785 {
00786     IIIMF_status st;
00787     IIIMCF_attr attr;
00788     IIIMCF_language lang;
00789     
00790     st = iiimcf_create_attr(&attr); 
00791     if (st != IIIMF_STATUS_SUCCESS) return st;
00792     lang = get_IM_language(im);
00793     if (lang) {
00794        st = iiimcf_attr_put_ptr_value(attr,
00795                                    IIIMCF_ATTR_INPUT_LANGUAGE,
00796                                    lang);
00797        if (st != IIIMF_STATUS_SUCCESS) goto exit;
00798     }
00799 
00800     if (XIM_IIIMP(im, engine_name)) {
00801        st = iiimcf_attr_put_string_value(attr,
00802                                      IIIMCF_ATTR_INPUT_METHOD_NAME,
00803                                      XIM_IIIMP(im, engine_name));
00804        if (st != IIIMF_STATUS_SUCCESS) goto exit;
00805     }
00806 
00807     st = iiimcf_create_context(XIM_IIIMP(im, handle), attr, pc);
00808     if (XIM_IIIMP(im, inited) == False) {
00809 #ifdef linux
00810        if (0 == strcmp(XIM_IIIMP(im, client_type), "IIIMX XIM Server")) {
00811            CreateKanaWindow(im->core.display);
00812        }
00813 #endif /* linux */
00814        XIM_IIIMP(im, inited) = True;
00815     }
00816 
00817 exit:
00818     iiimcf_destroy_attr(attr);
00819     return st;
00820 }
00821 
00822 Bool
00823 IMSetPrimaryLocale(
00824     XicCommon ic,
00825     char *input_locale
00826 )
00827 {
00828     IIIMCF_context c;
00829     char *orig;
00830     XimCommon im = (XimCommon)ic->core.im;
00831 
00832     orig = XIM_IIIMP(im, primary_locale);
00833     XIM_IIIMP(im, primary_locale) = input_locale;
00834     if (IMCreateIC(im, &c) != IIIMF_STATUS_SUCCESS) {
00835        XIM_IIIMP(im, primary_locale) = orig;
00836        return False;
00837     }
00838     iiimcf_destroy_context(XIC_IIIMP(ic, context));
00839     XIC_IIIMP(ic, context) = c;
00840 
00841     return True;
00842 }
00843 
00844 Bool
00845 IMChangeClientType(
00846     XimCommon im,
00847     char *client_type
00848 )
00849 {
00850     IIIMCF_handle h;
00851 
00852     XIM_IIIMP(im, client_type) = client_type;
00853     if (XIM_IIIMP(im, inited)) {
00854        /* im has already had context,
00855           so we cannot reset handle. */
00856        return False;
00857     }
00858     h = XIM_IIIMP(im, handle);
00859     if (IMCreateHandle(im) != IIIMF_STATUS_SUCCESS)
00860        return False;
00861     iiimcf_destroy_handle(h);
00862 
00863     return True;
00864 }
00865 
00866 /********************************************************************************
00867                        AUX load/start/done/draw/setvalues
00868  ********************************************************************************/
00869 
00870 static IIIMF_status
00871 IMSetupAuxObject(
00872     XimCommon im
00873 )
00874 {
00875     IIIMF_status st;
00876     IIIMCF_handle h;
00877     const IIIMCF_object_descriptor *pdesc;
00878     const IIIMCF_object_descriptor **ppdescs;
00879     IIIMCF_downloaded_object *pobjs;
00880     int i, n1, n2;
00881 
00882     h = XIM_IIIMP(im, handle);
00883     st = iiimcf_get_object_descriptor_list(h, &n1, &pdesc);
00884     if (st != IIIMF_STATUS_SUCCESS) return st;
00885     pobjs = (IIIMCF_downloaded_object*) malloc(sizeof(*pobjs) * n1);
00886     if (!pobjs) return IIIMF_STATUS_MALLOC;
00887     ppdescs = (const IIIMCF_object_descriptor**) malloc(sizeof(*ppdescs) * n1);
00888     if (!ppdescs) {
00889        free(pobjs);
00890        return IIIMF_STATUS_MALLOC;
00891     }
00892 
00893     for (i = 0, n2 = 0; i < n1; i++, pdesc++) {
00894        if (pdesc->predefined_id == IIIMP_IMATTRIBUTE_BINARY_GUI_OBJECT) {
00895            ppdescs[n2++] = pdesc;
00896        }
00897     }
00898     if (n2 > 0) {
00899        st =  iiimcf_get_downloaded_objects(h, n2, ppdescs, pobjs);
00900        if (st != IIIMF_STATUS_SUCCESS) {
00901            free(ppdescs);
00902            free(pobjs);
00903            return st;
00904        }
00905        for (i = 0; i < n2; i++) {
00906            IIimpAuxDownload(pobjs[i]);
00907        }
00908     }
00909     free(ppdescs);
00910     free(pobjs);
00911 
00912     return IIIMF_STATUS_SUCCESS;
00913 }
00914 
00915 Bool
00916 IMAuxSetValues(
00917     XicCommon ic,
00918     IIIMCF_event ev
00919 )
00920 {
00921     if (!ic) return False;
00922 
00923     if (iiimcf_forward_event(XIC_IIIMP(ic, context), ev)
00924        != IIIMF_STATUS_SUCCESS) return False;
00925     IMProcessIncomingEvent(ic);
00926 
00927     return True;
00928 }
00929 
00930 Bool
00931 IMAuxGetValues(
00932     XicCommon ic,
00933     IIIMCF_event ev
00934 )
00935 {
00936     if (!ic) return False;
00937 
00938     if (iiimcf_forward_event(XIC_IIIMP(ic, context), ev)
00939        != IIIMF_STATUS_SUCCESS) return False;
00940     IMProcessIncomingEvent(ic);
00941 
00942     return True;
00943 }
00944 
00945 void
00946 ic_change_conversion_mode (XicCommon ic, char *conv_mode)
00947 {
00948   IIIMCF_event ev;
00949   if (conv_mode && !strcmp ((char*)conv_mode, "on"))
00950     {
00951       IIIMF_status st;
00952       st = iiimcf_create_trigger_notify_event (CONV_ON, &ev);
00953       if (st != IIIMF_STATUS_SUCCESS)
00954        return;
00955     }
00956   else if (conv_mode && !strcmp ((char*)conv_mode, "off"))
00957     {
00958       IIIMF_status st;
00959       st = iiimcf_create_trigger_notify_event (CONV_OFF, &ev);
00960       if (st != IIIMF_STATUS_SUCCESS)
00961        return;
00962     }
00963   if (iiimcf_forward_event(XIC_IIIMP(ic, context), ev) != IIIMF_STATUS_SUCCESS)
00964     return;
00965   IMProcessIncomingEvent(ic);
00966 }
00967 
00968 /* convert UTF-16 to UTF-8 */
00969 static char *
00970 format_iiimcf_string (const IIIMP_card16 *u16str)
00971 {
00972   iconv_t *cd;
00973   char *inbuf, *outbuf;
00974   int inbytesleft, outbytesleft;
00975   IIIMP_card16 *pu;
00976   char *utf8str;
00977   int buflen;
00978 
00979   if (!u16str) return NULL;
00980 
00981   if ((cd = iconv_open ("UTF-8", "UTF-16")) == (iconv_t) -1)
00982     return NULL;
00983 
00984   inbytesleft = 0;
00985   pu = u16str;
00986   while (*pu) { ++pu; inbytesleft += sizeof (IIIMP_card16); }
00987   inbuf = (char *)u16str;
00988 
00989   /* The buflen should be big enough to hold the converted utf8 string */
00990   buflen = inbytesleft * 3;
00991   utf8str = (char *) malloc (buflen);
00992   memset (utf8str, 0, buflen);
00993   outbuf = utf8str;
00994   outbytesleft = buflen;
00995 
00996   iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
00997 
00998   iconv_close (cd);
00999 
01000   return utf8str;
01001 }
01002 
01003 /* convert UTF-8 to UTF-16 */
01004 static IIIMP_card16 *
01005 format_utf8_string (char *utf8str)
01006 {
01007   iconv_t *cd;
01008   char *inbuf, *outbuf;
01009   int inbytesleft, outbytesleft;
01010   IIIMP_card16 *u16str;
01011   int buflen;
01012 
01013   if (!utf8str) return NULL;
01014 
01015   if ((cd = iconv_open ("UTF-16", "UTF-8")) == (iconv_t) -1)
01016     return NULL;
01017 
01018   inbuf = utf8str;
01019   inbytesleft = strlen (utf8str);
01020 
01021   /* The buflen should be big enough to hold the converted UTF-16 string */
01022   buflen = inbytesleft;
01023   u16str = (IIIMP_card16 *) malloc (sizeof (IIIMP_card16) * buflen);
01024   memset (u16str, 0, buflen * sizeof (IIIMP_card16));
01025   outbuf = u16str;
01026   outbytesleft = buflen * sizeof (IIIMP_card16);
01027 
01028   iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
01029 
01030   iconv_close (cd);
01031 
01032   /* delete the first U+FEFF character */
01033 #define UNICODE_BOM 0xFEFF
01034   if (u16str[0] == UNICODE_BOM)
01035     memmove (u16str, u16str + 1, (buflen - 1) * sizeof (IIIMP_card16));
01036 
01037   return u16str;
01038 }
01039 
01040 void
01041 ic_initialize_with_input_language (XicCommon ic, char *new_lang)
01042 {
01043   IIIMCF_language iiim_lang = NULL;
01044   IIIMF_status st;
01045   IIIMCF_attr attr;
01046   IIIMCF_event ev;
01047   int conversion_mode = CONV_OFF;
01048   char *le_name = NULL;
01049   int i = 0, n;
01050   const IIIMP_card16 *u16idname, *u16hrn, *u16domain;
01051   Bool found_le = False;
01052   IIIMCF_input_method *pims;
01053   XimCommon im = (XimCommon)ic->core.im;
01054 
01055   if (XIC_IIIMP(ic, context) == NULL)
01056     return;
01057 
01058   if (new_lang)
01059     {
01060       /* FIXME just a workaround, to be modified later */
01061       char *p = strchr(new_lang, ':');
01062       if (p) 
01063        {
01064          *p = '\0';
01065          le_name = ++p;
01066        }
01067 
01068       iiim_lang = get_input_language (ic, new_lang, True);
01069       if (iiim_lang != NULL)
01070        {
01071          Xfree (ic->current_language);
01072          ic->current_language = strdup (new_lang);
01073        }
01074       else
01075        /* invalid new lang */
01076        return;
01077     }
01078   else
01079     iiim_lang = get_input_language (ic, ic->current_language, False);
01080 
01081   if (le_name != NULL)
01082     {
01083       char *idname = NULL;
01084       /* probably le_name consists of 'lename' and 'imename' which are 
01085        * separated by '-'.
01086        */
01087       const char *ime_delimiter = "-";
01088       char **le_ime = my_strsplit (le_name, ime_delimiter);
01089       char *lename = le_ime[0], *imename = le_ime[1];
01090 
01091       st = iiimcf_get_supported_input_methods (XIM_IIIMP (im, handle), &n, &pims);
01092       if (st != IIIMF_STATUS_SUCCESS)
01093        return;
01094 
01095       for (i = 0; i < n; i++)
01096        {
01097          st = iiimcf_get_input_method_desc (pims[i], &u16idname, &u16hrn,
01098                                         &u16domain);
01099          if (st != IIIMF_STATUS_SUCCESS)
01100            return;
01101 
01102          idname = format_iiimcf_string (u16hrn);
01103          if (idname != NULL && strcmp (lename, idname) == 0)
01104            {
01105              /* update the pims[i]->imname with the new imname that
01106               * consists imename.
01107               */
01108              if (imename)
01109               {
01110                 IIIMP_card16 *imname = format_utf8_string (le_name);
01111                 iiimcf_set_input_method_name (pims[i], imname);
01112               }
01113 
01114              free (idname);
01115              found_le = True;
01116              break;
01117            }
01118          if (idname != NULL)
01119            {
01120              free (idname);
01121              idname = NULL;
01122            }
01123        }
01124       if (lename) free (lename);
01125       if (le_ime) free (le_ime);
01126     }
01127 
01128   /* save conversion mode to restore this after switching */
01129   st = iiimcf_get_current_conversion_mode (XIC_IIIMP(ic, context),
01130                                       &conversion_mode);
01131 
01132   st = iiimcf_create_attr (&attr);
01133   if (st != IIIMF_STATUS_SUCCESS) 
01134     return;
01135   if (found_le)
01136       iiimcf_attr_put_ptr_value (attr, IIIMCF_ATTR_INPUT_METHOD,
01137                              pims[i]);
01138   if (iiim_lang)
01139       iiimcf_attr_put_ptr_value (attr, IIIMCF_ATTR_INPUT_LANGUAGE,
01140                              iiim_lang);
01141   st = iiimcf_context_set_attr(XIC_IIIMP(ic, context), attr);
01142   iiimcf_destroy_attr (attr);
01143   if (st != IIIMF_STATUS_SUCCESS)
01144     return; 
01145 
01146   /* NOTE: need to support the change of input language here.
01147    * and don't call ic_switcher_set_input_language here too.
01148    * it causes the infinite loop of PropertyNotify event
01149    * between xiiimp.so and gimlet.
01150    */
01151   /* ic_switcher_set_input_language(ic, NULL); */
01152   st = iiimcf_create_seticfocus_event (&ev);
01153 
01154   if (st != IIIMF_STATUS_SUCCESS)
01155     return;
01156 
01157   iiimcf_forward_event(XIC_IIIMP(ic, context), ev);
01158   if (conversion_mode)
01159     {
01160       st = iiimcf_create_trigger_notify_event (CONV_ON, &ev);
01161       if (st != IIIMF_STATUS_SUCCESS)
01162        return;
01163       iiimcf_forward_event(XIC_IIIMP(ic, context), ev);
01164     }
01165   IMProcessIncomingEvent(ic);
01166 }
01167 
01168 /* get Lang List */
01169 IIIMCF_language*
01170 iiim_get_languages (XimCommon im, int *n_lang)
01171 {
01172   IIIMF_status st;
01173   IIIMCF_handle h = XIM_IIIMP(im, handle);
01174   IIIMCF_language *lang = NULL;
01175 
01176   if (!h)
01177     return NULL;
01178 
01179   st = iiimcf_get_supported_languages (h, n_lang, &lang);
01180   if (st != IIIMF_STATUS_SUCCESS)
01181     return NULL;
01182 
01183   return lang;
01184 }
01185 
01186 static IIIMCF_language
01187 get_input_language (XicCommon ic, char *input_language, Bool exact_match)
01188 {
01189   int i;
01190   IIIMF_status st;
01191   char *langid, *lang, *p;
01192   int n_lang;
01193   IIIMCF_language *lang_list;
01194   XimCommon im = (XimCommon)ic->core.im;
01195 
01196   if (input_language == NULL)
01197       return NULL;
01198   else
01199       lang = strdup(input_language);
01200 
01201   lang_list = iiim_get_languages (im, &n_lang);
01202   if (lang_list)
01203     {
01204       for (i = 0; i < n_lang; i++)
01205        {
01206          st = iiimcf_get_language_id(lang_list[i], (const char **)&langid);
01207          if (st != IIIMF_STATUS_SUCCESS)
01208            continue;
01209          if (!strcmp(lang, langid))
01210            goto found_language;
01211        }
01212       /* try to find the supported language again without charset locale */
01213       p = strchr(lang, '@');
01214       if (p)
01215        *p = 0;
01216       p = strchr(lang, '.');
01217       if (p)
01218        *p = 0;
01219 
01220       for (i = 0; i < n_lang; i++)
01221        {
01222          st = iiimcf_get_language_id(lang_list[i], (const char **)&langid);
01223          if (st != IIIMF_STATUS_SUCCESS)
01224            continue;
01225          if (!strcmp(lang, langid))
01226            goto found_language;
01227        }
01228       /* finally try to take care of the locale, such as en */
01229       p = strchr(lang, '_');
01230       if (p)
01231        *p = 0;
01232 
01233       for (i = 0; i < n_lang; i++)
01234        {
01235          st = iiimcf_get_language_id(lang_list[i], (const char **)&langid);
01236          if (st != IIIMF_STATUS_SUCCESS)
01237            continue;
01238          if (!strcmp(lang, langid))
01239            goto found_language;
01240        }
01241       free(lang);
01242 
01243       /*
01244        still cannot find a match. Just take one for "en" as
01245        a default.
01246       */
01247       for (i = 0; i < n_lang; i++)
01248        {
01249          st = iiimcf_get_language_id (lang_list[i],
01250                                    (const char **)&langid);
01251          if (st != IIIMF_STATUS_SUCCESS)
01252            continue;
01253          if (!strncmp (langid, "en", 2))
01254            goto found_language;
01255        }
01256     }
01257 
01258   return NULL;
01259 
01260  found_language:;
01261   Xfree(ic->current_language);
01262   ic->current_language = strdup(langid);
01263 
01264   return lang_list[i];
01265 }
01266 
01267 /* Local Variables: */
01268 /* c-file-style: "iiim-project" */
01269 /* End: */