Back to index

im-sdk  12.3.91
iiimpConv.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 #if !defined(USE_ICONV) && !defined(USE_CSCONV)
00044 #if defined(sun)
00045 #define USE_ICONV
00046 #else
00047 #define USE_ICONV
00048 #endif
00049 #endif
00050 
00051 #ifdef USE_ICONV
00052 #include <iconv.h> 
00053 #endif
00054 
00055 #include <locale.h>
00056 #include <langinfo.h>
00057 #include <strings.h>
00058 #if !defined(USE_CSCONV)
00059 #include <errno.h>
00060 #endif /* !USE_CSCONV */
00061 #include "iiimpIM.h"
00062 #include "xiiimp.h"
00063 #include "iiimpReq.h"
00064 #include "iiimpColor.h"
00065 #include "iiimpConv.h"
00066 
00067 #define UTF16_STRLEN 4096
00068 
00069 #ifdef USE_CSCONV
00070 #include <dlfcn.h>
00071 #include "csconv.h"
00072 #define CSC_PATH     IIIMLIBDIR "/csconv/csconv.so"
00073 #define CSC_OPEN_LOCALE     "csconv_open_locale"
00074 #define CSC_OPEN     "csconv_open"
00075 #define CSC_CONV     "csconv"
00076 #define CSC_CLOSE    "csconv_close"
00077 
00078 typedef csconv_t     (* csc_open_locale_t)(const char *,
00079                                          const char *, const char *);
00080 typedef csconv_t     (* csc_open_t)(const char *, const char *);
00081 typedef size_t              (* csc_conv_t)(csconv_t, const char **, size_t *,
00082                                    char **, size_t *);
00083 typedef int          (* csc_close_t)(csconv_t);
00084 
00085 static void *               csc_handle;   
00086 static csc_open_locale_t    csc_open_locale;
00087 static csc_open_t           csc_open;
00088 static csc_conv_t           csc_conv;
00089 static csc_close_t          csc_close;
00090 
00091 static char *current_locale = 0;
00092 #endif
00093 
00094 #ifdef USE_ICONV
00095 static iconv_t i_conv1 = NULL;
00096 static iconv_t i_conv2 = NULL;
00097 static Bool skip_native_to_utf8_conv = False;
00098 #endif
00099 
00100 #ifdef USE_CSCONV
00101 static void
00102 dlopen_csconv()
00103 {
00104     csc_handle = dlopen(CSC_PATH, RTLD_LAZY);
00105     if (NULL == csc_handle) {
00106        csc_handle = (void *)(-1);
00107        return;
00108     }
00109 
00110     csc_open_locale = (csc_open_locale_t)dlsym(csc_handle, CSC_OPEN_LOCALE);
00111     csc_open = (csc_open_t)dlsym(csc_handle, CSC_OPEN);
00112     csc_conv = (csc_conv_t)dlsym(csc_handle, CSC_CONV);
00113     csc_close = (csc_close_t)dlsym(csc_handle, CSC_CLOSE);
00114 
00115     if ((NULL == csc_open_locale) || (NULL == csc_open) ||
00116        (NULL == csc_conv) || (NULL == csc_close)) {
00117        dlclose(csc_handle);
00118        csc_handle = (void *)(-1);
00119        return;
00120     }
00121 }
00122 #endif
00123 
00124 static int
00125 ConvertToUTF16(
00126     char *current_encoding,
00127     char *from_buf,
00128     size_t from_left,
00129     char **to_buf,
00130     size_t *to_left
00131 )
00132 {
00133     size_t src_len, dst_len;
00134     char *src, *dst;
00135 #ifndef USE_CSCONV
00136     const char *ip;
00137     size_t ileft;
00138     char *op;
00139     size_t oleft;
00140     char buffer[UTF16_STRLEN];            /* Fix me! */
00141 #endif /* !USE_CSCONV */
00142     const size_t buf_len = UTF16_STRLEN;
00143     size_t ret = 0;
00144 #ifdef USE_CSCONV
00145     static csconv_t csconv_cd = NULL;
00146 
00147 #endif
00148 
00149     if (current_encoding == NULL) return 0;
00150 
00151 #ifdef USE_CSCONV
00152 
00153     do {
00154        if (((void *)(-1) == csc_handle) ||
00155            ((csconv_t)(-1) == csconv_cd)) {
00156            continue;
00157        }
00158        if (NULL == csc_handle) {
00159            dlopen_csconv();
00160            if ((void *)(-1) == csc_handle) {
00161               continue;
00162            }
00163        }
00164        if (NULL == csconv_cd) {
00165 
00166            csconv_cd = (csc_open_locale)(current_encoding,
00167                                      "UTF-16", "MultiByte");
00168       
00169            if ((csconv_t)(-1) == csconv_cd) {
00170               continue;
00171            }
00172        }
00173 
00174        dst = *((char **)to_buf);
00175 
00176        ret = csc_conv(csconv_cd,
00177                      (const char **)&from_buf, &from_left,
00178                      &dst, to_left);
00179        return ret;
00180     } while (0);
00181 #endif
00182 
00183 #ifdef USE_ICONV
00184     if (i_conv1 == (iconv_t)-1 || i_conv2 == (iconv_t)-1){
00185        goto done;
00186     }
00187 
00188     if (i_conv1 == NULL && !skip_native_to_utf8_conv) {
00189        if (!strcmp(current_encoding, "UTF-8")) {
00190            skip_native_to_utf8_conv = True;
00191        } else {
00192            if ((i_conv1 = iconv_open("UTF-8", current_encoding))
00193               == (iconv_t)-1) {
00194               /* fallback */
00195               current_encoding = "646";
00196               if ((i_conv1 = iconv_open("UTF-8", current_encoding))
00197                   == (iconv_t)-1)
00198                   goto done;
00199            }
00200        }
00201     }
00202 
00203     if (i_conv2 == NULL){
00204        if ((i_conv2 = iconv_open("UTF-16",
00205                               "UTF-8")) == (iconv_t)-1)
00206            goto done;
00207     }
00208 
00209     if (!skip_native_to_utf8_conv) {
00210        ip = (const char *)from_buf;
00211        ileft = from_left;
00212 
00213        op = *((char **)to_buf);
00214        oleft = *to_left;
00215 
00216        while ((0 < ileft) && (0 < oleft)) {
00217            dst = buffer;
00218            dst_len = buf_len;
00219            ret = iconv(i_conv1, &ip, &ileft, (char**)&dst, &dst_len);
00220            if ((ret != 0) && (E2BIG != errno)) {
00221               goto done;
00222            }
00223 
00224            src = buffer;
00225            src_len = buf_len - dst_len;
00226 
00227            ret = iconv(i_conv2, (const char**)&src, &src_len, &op, &oleft);
00228            if (ret != 0) goto done;
00229        }
00230 
00231        dst_len = oleft;
00232 
00233     } else {
00234        src = from_buf;
00235        src_len = from_left;
00236        dst = *to_buf;
00237        dst_len = *to_left;
00238 
00239        ret = iconv(i_conv2, (const char**)&src, &src_len, (char**)&dst, &dst_len);
00240     }
00241 
00242     if (0xFEFF == **((CARD16 **)to_buf)) {
00243        memmove(*to_buf, *to_buf + 2, *to_left - dst_len - 2);
00244        *to_left = (dst_len + 2);
00245     } else {
00246        *to_left = dst_len;
00247     }
00248 done:
00249 #endif /* USE_ICONV */
00250     return ret;
00251 }
00252 
00253 /* this function should be only used from composeIM. */
00254 int
00255 IMConvertFromUTF8ToUTF16(
00256     char *from_buf,
00257     size_t from_left,
00258     char **to_buf,
00259     size_t *to_left)
00260 {
00261     char *encoding;
00262     int ret;
00263 #ifdef USE_CSCONV
00264     encoding = "en_US.UTF-8";
00265 #else
00266     int restore = False;
00267     encoding = "UTF-8";
00268     if (!skip_native_to_utf8_conv) {
00269        restore = True;
00270        skip_native_to_utf8_conv = True;
00271     }
00272 #endif
00273     ret = ConvertToUTF16(encoding,
00274                       from_buf, from_left,
00275                       to_buf, to_left);
00276 #ifndef USE_CSCONV
00277     if (restore)
00278        skip_native_to_utf8_conv = False;
00279 #endif
00280 
00281     return ret;
00282 }
00283 
00284 #ifdef USE_ICONV
00285 static iconv_t i_conv1_FromUTF16 = NULL;
00286 static iconv_t i_conv2_FromUTF16 = NULL;
00287 #endif
00288 
00289 int
00290 IMConvertFromUTF8(
00291     char *from_buf,
00292     size_t from_left,
00293     char **to_buf,
00294     size_t *to_left
00295 )
00296 {
00297     size_t ret = 0;
00298 #ifdef USE_CSCONV
00299     static csconv_t csconv_cd = NULL;
00300 #endif
00301 
00302 #ifdef USE_ICONV
00303     if (skip_native_to_utf8_conv)
00304        return -1;
00305 
00306     if (i_conv2_FromUTF16 == (iconv_t)-1)
00307        /* already failed */
00308        return -1;
00309 
00310     if (i_conv2_FromUTF16 == NULL) {
00311        char *encoding = nl_langinfo(CODESET);
00312 
00313        if (!strcmp(encoding, "UTF-8")) {
00314            skip_native_to_utf8_conv = True;
00315            return -1;
00316        } else {
00317            if ((i_conv2_FromUTF16 = iconv_open(encoding, "UTF-8"))
00318               == (iconv_t) - 1) {
00319               /* fallback */
00320               encoding = "646";
00321               if ((i_conv2_FromUTF16 = iconv_open(encoding, "UTF-8"))
00322                   == (iconv_t) - 1)
00323                   goto done;
00324            }
00325        }
00326     }
00327 
00328     ret = iconv(i_conv2_FromUTF16, (const char**)&from_buf, &from_left,
00329               to_buf, to_left);
00330 done:
00331 #endif /* USE_ICONV */
00332 
00333     return ret;
00334 }
00335 
00336 #ifdef USE_ICONV
00337 static iconv_t i_conv_ToUTF8 = NULL;
00338 #endif
00339 
00340 int
00341 IMConvertToUTF8(
00342     char *from_buf,
00343     size_t from_left,
00344     char **to_buf,
00345     size_t *to_left
00346 )
00347 {
00348   size_t ret = 0;
00349 #ifdef USE_CSCONV
00350   static csconv_t csconv_cd = NULL;
00351 #endif
00352 
00353 #ifdef USE_ICONV
00354   if (skip_native_to_utf8_conv) {
00355     strcpy (to_buf, from_buf);
00356     *to_left -= from_left;
00357     return ret;
00358   }
00359 
00360   if (i_conv_ToUTF8 == (iconv_t)-1)
00361     /* already failed */
00362     return -1;
00363 
00364   if (i_conv_ToUTF8 == NULL) {
00365     char *encoding = nl_langinfo(CODESET);
00366 
00367     if (!strcmp(encoding, "UTF-8")) {
00368       skip_native_to_utf8_conv = True;
00369       strcpy (to_buf, from_buf);
00370       *to_left -= from_left;
00371       return ret;
00372     } else {
00373       if ((i_conv_ToUTF8 = iconv_open("UTF-8", encoding))
00374          == (iconv_t) - 1) {
00375        /* fallback */
00376        encoding = "646";
00377        if ((i_conv_ToUTF8 = iconv_open("UTF-8", encoding))
00378            == (iconv_t) - 1)
00379          goto done;
00380       }
00381     }
00382   }
00383 
00384   ret = iconv(i_conv_ToUTF8, (const char**)&from_buf, &from_left,
00385              to_buf, to_left);
00386  done:
00387 #endif /* USE_ICONV */
00388 
00389   return ret;
00390 }
00391 
00392 int
00393 IIimpConvertToUTF16(
00394     char *from_buf,
00395     size_t from_left,
00396     char **to_buf,
00397     size_t *to_left
00398 )
00399 {
00400 #ifdef USE_CSCONV
00401     if (current_locale == NULL){
00402        current_locale = (char*)strdup(setlocale(LC_CTYPE, NULL));
00403     }
00404     return ConvertToUTF16(current_locale,
00405                        from_buf, from_left,
00406                        to_buf, to_left);
00407 #else
00408     char *encoding = nl_langinfo(CODESET);
00409     return ConvertToUTF16(encoding,
00410                        from_buf, from_left,
00411                        to_buf, to_left);
00412 #endif
00413 }
00414 
00415 /* Used when transfering data from AUX to IM,
00416    do data conversion from UTF16 to EUC */
00417 int
00418 IIimpConvertFromUTF16(
00419     const char *from_buf,
00420     size_t from_left,
00421     char **to_buf,
00422     size_t * to_left
00423 )
00424 {
00425     size_t src_len, dst_len;
00426     char *src, *dst;
00427 #ifndef USE_CSCONV
00428     const char *ip;
00429     size_t ileft;
00430     char *op;
00431     size_t oleft;
00432     char buffer[UTF16_STRLEN];     /* Fix me! */
00433 #endif /* !USE_CSCONV */
00434     const size_t buf_len = UTF16_STRLEN;
00435     size_t ret = 0;
00436 
00437 #ifdef USE_CSCONV
00438     static csconv_t csconv_cd = NULL;
00439 #endif
00440 
00441 #ifdef USE_CSCONV
00442     if (current_locale == NULL){
00443        current_locale = (char*)strdup(setlocale(LC_CTYPE, NULL));
00444     }
00445     do {
00446        if (((void *)(-1) == csc_handle) ||
00447            ((csconv_t)(-1) == csconv_cd)) {
00448            continue;
00449        }
00450        if (NULL == csc_handle) {
00451            dlopen_csconv();
00452            if ((void *)(-1) == csc_handle) {
00453               continue;
00454            }
00455        }
00456        if (NULL == csconv_cd) {
00457 
00458            csconv_cd = (csc_open_locale)(current_locale, "MultiByte", "UTF-16");
00459       
00460            if ((csconv_t)(-1) == csconv_cd) {
00461               continue;
00462            }
00463        }
00464 
00465        dst = *((char **)to_buf);
00466 
00467        ret = csc_conv(csconv_cd,
00468                      &from_buf, &from_left, &dst, to_left);
00469        return ret;
00470     } while (0);
00471 #endif
00472 
00473 #ifdef USE_ICONV
00474     if (i_conv1_FromUTF16 == (iconv_t)-1 ||
00475        i_conv2_FromUTF16 == (iconv_t)-1) {
00476        goto done;
00477     }
00478 
00479     if (i_conv2_FromUTF16 == NULL && !skip_native_to_utf8_conv) {
00480        char *encoding = nl_langinfo(CODESET);
00481        if (!strcmp(encoding, "UTF-8")) {
00482            skip_native_to_utf8_conv = True;
00483        } else {
00484            if ((i_conv2_FromUTF16 = iconv_open(encoding, "UTF-8"))
00485               == (iconv_t) - 1) {
00486               /* fallback */
00487               encoding = "646";
00488               if ((i_conv2_FromUTF16 = iconv_open(encoding, "UTF-8"))
00489                   == (iconv_t) - 1)
00490                   goto done;
00491            }
00492        }
00493     }
00494     if (i_conv1_FromUTF16 == NULL) {
00495        if ((i_conv1_FromUTF16 = iconv_open("UTF-8", "UTF-16"))
00496            == (iconv_t) - 1) {
00497            goto done;
00498        }
00499     }
00500 
00501     if (skip_native_to_utf8_conv) {
00502        src = from_buf;
00503        src_len = from_left; /* don't stop at '\0' in case of ascii */
00504        dst = *((char **) to_buf);
00505 
00506        ret = iconv(i_conv1_FromUTF16, (const char**)&src, &src_len,
00507                   (char**)&dst, to_left);
00508     } else {
00509        ip = (const char *)from_buf;
00510        ileft = from_left;
00511 
00512        op = *((char **)to_buf);
00513        oleft = *to_left;
00514 
00515        while ((0 < ileft) && (0 < oleft)) {
00516            dst = buffer;
00517            dst_len = buf_len;
00518            ret = iconv(i_conv1_FromUTF16, &ip, &ileft, (char**)&dst, &dst_len);
00519            if ((ret != 0) && (E2BIG != errno)) {
00520               goto done;
00521            }
00522 
00523            src = buffer;
00524            src_len = buf_len - dst_len;
00525 
00526            ret = iconv(i_conv2_FromUTF16, (const char**)&src, &src_len,
00527                      &op, &oleft);
00528            if (ret != 0) goto done;
00529        }
00530 
00531        *to_left = oleft;
00532     }
00533 done:
00534 #endif /* USE_ICONV */
00535     return ret;
00536 }
00537 
00538 static IIIMF_status
00539 UTF16ToString(
00540     int len,
00541     const IIIMP_card16 *ucstr,
00542     Bool useUnicode,
00543     char **pstr
00544 )
00545 {
00546     if (len == 0) {
00547        *pstr = NULL;
00548        return IIIMF_STATUS_SUCCESS;
00549     }
00550 
00551     if (useUnicode) {
00552        IIIMP_card16 *ustr;
00553 
00554        ustr = (IIIMP_card16*) Xmalloc(sizeof(*ustr) * (len + 1));
00555        if (!ustr) return IIIMF_STATUS_MALLOC;
00556        memcpy(ustr, ucstr, sizeof(*ucstr) * len);
00557        ustr[len] = 0;
00558        *pstr = (char*) ustr;
00559 
00560        return IIIMF_STATUS_SUCCESS;
00561     } else {
00562        int dst_len, dst_len_orig, src_len;
00563        char *str;
00564        const char *src;
00565 
00566        str = (char*) Xmalloc(len * MB_CUR_MAX + 1);
00567        if (!str) return IIIMF_STATUS_MALLOC;
00568        dst_len = dst_len_orig = len * MB_CUR_MAX;
00569        src_len = len * sizeof(IIIMP_card16);
00570 
00571        src = (const char*) ucstr;
00572        IIimpConvertFromUTF16(src, src_len, &str, &dst_len);
00573        str[dst_len_orig - dst_len] = '\0';
00574        *pstr = str;
00575     }
00576 
00577     return IIIMF_STATUS_SUCCESS;
00578 }
00579 
00580 IIIMF_status
00581 IIimpUTF16ToString(
00582     const IIIMP_card16 *ucstr,
00583     Bool useUnicode,
00584     char **pstr
00585 )
00586 {
00587     int len;
00588 
00589     for (len = 0; ucstr[len]; len++);
00590     return UTF16ToString(len, ucstr, useUnicode, pstr);
00591 }
00592 
00593 IIIMF_status
00594 IIimpConvertToString(
00595     IIIMCF_text text,
00596     Bool useUnicode,
00597     char **pstr
00598 )
00599 {
00600     IIIMF_status st;
00601     int len;
00602     const IIIMP_card16 *ucstr;
00603 
00604     st = iiimcf_get_text_length(text, &len); 
00605     if (st != IIIMF_STATUS_SUCCESS) return st;
00606     if (len == 0) {
00607        *pstr = NULL;
00608        return IIIMF_STATUS_SUCCESS;
00609     }
00610     st = iiimcf_get_text_utf16string(text, &ucstr);
00611     if (st != IIIMF_STATUS_SUCCESS) return st;
00612 
00613     return UTF16ToString(len, ucstr, useUnicode, pstr);
00614 }
00615 
00616 IIIMF_status
00617 IIimpConvertToXIMText(
00618     IIIMCF_text text,
00619     XIMText *pxt,
00620     IMFeedbackList **ppfeedbacks,
00621     Bool useUnicode
00622 )
00623 {
00624     IIIMF_status st;
00625     IIIMP_card16 ch;
00626     const IIIMP_card32 *pids, *pfbs;
00627     XIMFeedback *ximfb = NULL, *ximfb_top = NULL;
00628     IMFeedbackList *pfl = NULL, *pfl2 = NULL;
00629     IMFeedback *pfb, *pfb2;
00630     int i, len;
00631     int j, nfb;
00632     Bool has_feedback = False;
00633 
00634     memset(pxt, 0, sizeof(*pxt));
00635     st = iiimcf_get_text_length(text, &len); 
00636     if (st != IIIMF_STATUS_SUCCESS) goto error;
00637     if (len == 0) {
00638        if (ppfeedbacks) *ppfeedbacks = NULL;
00639        return IIIMF_STATUS_SUCCESS;
00640     }
00641 
00642     pfl = pfl2 = NULL;
00643     ximfb_top = ximfb = (XIMFeedback*) Xmalloc(sizeof(*ximfb) * len);
00644     memset(ximfb, 0, sizeof(*ximfb) * len);
00645     if (!ximfb) goto memory_error;
00646     if (ppfeedbacks) {
00647        pfl = pfl2 = (IMFeedbackList*) Xmalloc(sizeof(*pfl) * len);
00648        if (!pfl) goto memory_error;
00649        memset(pfl, 0, sizeof(*pfl) * len);
00650     }
00651     pxt->feedback = ximfb;
00652     pxt->length = len;
00653 
00654     for (i = 0; i < len; i++, ximfb++) {
00655        st = iiimcf_get_char_with_feedback(text, i, &ch, &nfb, &pids, &pfbs);
00656        if (st != IIIMF_STATUS_SUCCESS) goto error;
00657        if (pfl) {
00658            int count_nfb = 0;
00659            pfb = pfb2 = (IMFeedback*) Xmalloc(sizeof(IMFeedback) * nfb);
00660            if (!pfb) goto memory_error;
00661            for (j = 0; j < nfb; j++, pids++, pfbs++) {
00662               if (*pids == 0)
00663                 *ximfb = *pfbs;
00664               else {
00665                 has_feedback = True;
00666                 pfb2->type = *pids;
00667                 pfb2->value = *pfbs;
00668                 pfb2++;
00669                 count_nfb++;
00670               }
00671            }
00672            pfl2->count_feedbacks = count_nfb;
00673            pfl2->feedbacks = pfb;
00674            pfl2++;
00675        } else {
00676            for (j = 0; j < nfb; j++, pids++) {
00677               if (*pids == 0) {
00678                   *ximfb = pfbs[j];
00679                   break;
00680               }
00681            }
00682        }
00683     }
00684 
00685     st = IIimpConvertToString(text, useUnicode, &pxt->string.multi_byte);
00686     if (st != IIIMF_STATUS_SUCCESS) goto error;
00687 
00688     if (ppfeedbacks) {
00689       if (!has_feedback) {
00690        FreeFeedbackList(pfl, len);
00691         pfl = NULL;
00692       }
00693       *ppfeedbacks = pfl;
00694     }
00695 
00696     return IIIMF_STATUS_SUCCESS;
00697 
00698 memory_error:
00699     st = IIIMF_STATUS_MALLOC;
00700 error:
00701     if (ximfb_top) free(ximfb_top);
00702     if (pfl) FreeFeedbackList(pfl, len);
00703     if (pxt->string.multi_byte) free(pxt->string.multi_byte);
00704 
00705     return st;
00706 }
00707 
00708 #ifndef MAXINT
00709 #define MAXINT          (~((unsigned int)1 << (8 * sizeof(int)) - 1))
00710 #endif /* !MAXINT */
00711 
00712 int
00713 IIimpWcstoMbs(XimCommon im, wchar_t *from, int from_len,
00714              char *to, int to_len, Status *state) {
00715   XlcConv conv = im->wtom_conv;
00716   int from_left;
00717   int to_left;
00718   int from_savelen;
00719   int to_savelen;
00720   int from_cnvlen;
00721   int to_cnvlen;
00722   wchar_t *from_buf;
00723   char *to_buf, *tmp_buf;
00724   Status tmp_state;
00725 
00726   if (!state)
00727     state = &tmp_state;
00728 
00729   if (!conv || !from || !from_len) {
00730     *state = XLookupNone;
00731     return 0;
00732   }
00733 
00734   if (*from == (wchar_t)0) {
00735     to[0] = (char)0;
00736     return 0;
00737   }
00738   if (to && to_len) {
00739     from_left = from_len;
00740     to_left = to_len;
00741     from_cnvlen = 0;
00742     to_cnvlen = 0;
00743     for (;;) {
00744       from_savelen = from_left;
00745       to_savelen = to_left;
00746       from_buf = &from[from_cnvlen];
00747       to_buf = &to[to_cnvlen];
00748       if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
00749                     (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
00750        *state = XLookupNone;
00751        return 0;
00752       }
00753       from_cnvlen += (from_savelen - from_left);
00754       to_cnvlen += (to_savelen - to_left);
00755       if (from_left == 0) {
00756        if (to_cnvlen > 0) {
00757          *state = XLookupChars;
00758        } else {
00759          *state = XLookupNone;
00760        }
00761        return to_cnvlen;
00762       }
00763       if (to_left == 0)
00764        break;
00765       /* Overflow : the to_left length is so small that it cannot
00766          accomodate the first mb character in the next conversion block */
00767       if (to_left < MB_CUR_MAX)
00768          break;
00769     }
00770   }
00771 
00772   from_left = from_len;
00773   from_cnvlen = 0;
00774   to_cnvlen = 0;
00775   /* BugId : 4253988. In case the from_buf is bigger than the to_buffer,
00776        we need to return the required buffer size and status as XBufferOverflow.
00777        We create a tmp buffer equals 8 times the from_len and do conversion.
00778   */
00779   to_left = (sizeof(wchar_t) * from_len) ;
00780   tmp_buf = (char *)malloc(to_left);
00781   for (;;) {
00782     from_savelen = from_left;
00783     from_buf = &from[from_cnvlen];
00784     to_savelen = to_left;
00785     to_buf = &tmp_buf[to_cnvlen];
00786     if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
00787                   (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
00788       *state = XLookupNone;
00789       return 0;
00790     }
00791     from_cnvlen += (from_savelen - from_left);
00792     to_cnvlen += (to_savelen - to_left);
00793     if (from_left == 0) {
00794       if (to_cnvlen > 0)
00795        *state = XBufferOverflow;
00796       else
00797        *state = XLookupNone;
00798       break;
00799     }
00800   }
00801   free(tmp_buf);
00802   return to_cnvlen;
00803 }
00804 
00805 int
00806 IIimpMbstoWcs(XimCommon im, char *from, int from_len,
00807              wchar_t *to, int to_len, Status *state) {
00808   XlcConv conv = im->mtow_conv;
00809   int from_left;
00810   int to_left;
00811   int from_savelen;
00812   int to_savelen;
00813   int from_cnvlen;
00814   int to_cnvlen;
00815   char *from_buf;
00816   wchar_t *to_buf, *tmp_buf;
00817   Status tmp_state;
00818 
00819   if (!state)
00820     state = &tmp_state;
00821 
00822   /* Change to_len as to_len * sizeof(wchar_t)  - byte length */
00823   to_len = to_len * sizeof(wchar_t); 
00824   if (!conv || !from || !from_len) {
00825     *state = XLookupNone;
00826     return 0;
00827   }
00828 
00829   if (to && to_len) {
00830     from_left = from_len;
00831     to_left = to_len;
00832     from_cnvlen = 0;
00833     to_cnvlen = 0;
00834     for (;;) {
00835       from_savelen = from_left;
00836       to_savelen = to_left;
00837       from_buf = &from[from_cnvlen];
00838       to_buf = &to[to_cnvlen];
00839       if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
00840                     (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
00841        *state = XLookupNone;
00842        return 0;
00843       }
00844       from_cnvlen += (from_savelen - from_left);
00845       to_cnvlen += (to_savelen - to_left);
00846       if (from_left == 0) {
00847        if (to_cnvlen > 0) {
00848          *state = XLookupChars;
00849        } else {
00850          *state = XLookupNone;
00851        }
00852        return to_cnvlen;
00853       }
00854       if (to_left == 0)
00855        break;
00856       /* Overflow : the to_left length is so small that it cannot
00857          accomodate the first mb character in the next conversion block */
00858       if (to_left < sizeof(wchar_t)) {
00859          break;
00860       }
00861     }
00862   }
00863   from_left = from_len;
00864   from_cnvlen = 0;
00865   to_cnvlen = 0;
00866   /* BugId : 4253988. In case the from_buf is bigger than the to_buffer,
00867        we need to return the required buffer size and status as XBufferOverflow.
00868        We create a tmp buffer equals 8 times the from_len and do conversion.
00869   */
00870   to_left = from_len ;
00871   tmp_buf = (wchar_t *)malloc(to_left * sizeof(wchar_t));
00872   for (;;) {
00873     from_savelen = from_left;
00874     from_buf = &from[from_cnvlen];
00875     to_savelen = to_left;
00876     to_buf = &tmp_buf[to_cnvlen];
00877     from_buf = &from[from_cnvlen];
00878     if (_XlcConvert(conv, (XPointer *)&from_buf, &from_left,
00879                   (XPointer *)&to_buf, &to_left, NULL, 0) < 0) {
00880       *state = XLookupNone;
00881       return 0;
00882     }
00883     from_cnvlen += (from_savelen - from_left);
00884     to_cnvlen += (to_savelen - to_left);
00885     if (from_left == 0) {
00886       if (to_cnvlen > 0)
00887        *state = XBufferOverflow;
00888       else
00889        *state = XLookupNone;
00890       break;
00891     }
00892   }
00893   free(tmp_buf);
00894   return to_cnvlen;
00895 }
00896 
00897 /* Local Variables: */
00898 /* c-file-style: "iiim-project" */
00899 /* End: */