Back to index

im-sdk  12.3.91
encode.c
Go to the documentation of this file.
00001 /*
00002 Copyright 1990-2003 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 <stdio.h>
00044 #include <errno.h>
00045 #include <iconv.h>
00046 #include <strings.h>
00047 #include <X11/Xmd.h>
00048 #include "encode.h"
00049 
00050 typedef struct _LangGroup_Info {
00051        int    lang_id;
00052        char   *lang_name;
00053        int    *support_encodes;
00054        char   **support_locales;
00055 } LangGroup_Info;
00056 
00057 /* supported encodes for specified language */
00058 int zh_CN_encodes[] = {
00059        ENCODE_GB2312,
00060        ENCODE_GBK,
00061        ENCODE_GB18030,
00062        ENCODE_ERROR,
00063 };
00064 
00065 int zh_TW_encodes[] = {
00066        ENCODE_BIG5,
00067        ENCODE_EUC_TW,
00068        ENCODE_ERROR,
00069 };
00070 
00071 int zh_HK_encodes[] = {
00072        ENCODE_BIG5HK,
00073        ENCODE_ERROR,
00074 };
00075 
00076 int th_TH_encodes[] = {
00077        ENCODE_EUC_TH,
00078        ENCODE_ERROR,
00079 };
00080 
00081 int ko_KR_encodes[] = {
00082        ENCODE_EUC_KO,
00083        ENCODE_ERROR,
00084 };
00085 
00086 /* supported locales for specified language */
00087 char *zh_CN_locales[] = {
00088        "zh_CN",
00089        "zh_CN.EUC",
00090        "zh_CN.GBK",
00091        "zh_CN.GB18030",
00092        "zh_CN.UTF-8",
00093        "zh_CN.utf8",    /* for Linux */
00094        "zh.GBK",
00095        "zh.UTF-8",
00096        "zh",
00097        NULL
00098 };
00099 
00100 char *zh_TW_locales[] = {
00101        "zh_TW.eucTW",
00102        "zh_TW.EUC",
00103        "zh_TW.BIG5",
00104        "zh_TW.UTF-8",
00105        "zh_TW.utf8",    /* for Linux */
00106        "zh_TW",
00107        NULL
00108 };
00109 
00110 char *zh_HK_locales[] = {
00111        "zh_HK.big5hkscs",
00112        "zh_HK.BIG5HK",
00113        "zh_HK.UTF-8",
00114        "zh_HK.utf8",    /* for Linux */
00115        NULL
00116 };
00117 
00118 char *th_TH_locales[] = {
00119        "th_TH.TIS620",
00120        "th_TH.ISO8859-11",
00121        "th_TH.UTF-8",
00122        "th_TH.utf8",    /* for Linux */
00123        "th_TH",
00124        "th",
00125        NULL
00126 };
00127 
00128 char *ko_KR_locales[] = {
00129        "ko",
00130        "ko_KR.EUC",
00131        "ko.UTF-8",
00132        "ko_KR.utf8",    /* for Linux */
00133        NULL
00134 };
00135 
00136 LangGroup_Info langgroup_info[LANGS_NUM] = {
00137        {
00138               LANG_ZH_CN,
00139               "zh_CN",
00140               zh_CN_encodes,
00141               zh_CN_locales,
00142        },
00143        {
00144               LANG_ZH_TW,
00145               "zh_TW",
00146               zh_TW_encodes,
00147               zh_TW_locales,
00148        },
00149        {
00150               LANG_ZH_HK,
00151               "zh_HK",
00152               zh_HK_encodes,
00153               zh_HK_locales,
00154        },
00155        {
00156               LANG_TH_TH,
00157               "th_TH",
00158               th_TH_encodes,
00159               th_TH_locales,
00160        },
00161        {
00162               LANG_KO_KR,
00163               "ko_KR",
00164               ko_KR_encodes,
00165               ko_KR_locales,
00166        },
00167 };
00168 
00169 typedef struct _Encode_Info {
00170        int    encode_id;
00171        char   **called_names;
00172        char   **support_locales;
00173        char   *iconv_codeset_name;
00174        iconv_t fd_iconv_to_utf8;
00175        iconv_t fd_iconv_from_utf8;
00176 } Encode_Info;
00177 
00178 /* encode names */
00179 char *GB2312_names[] = {
00180        "GB2312",
00181        "GB",
00182        NULL
00183 };
00184 
00185 char *GBK_names[] = {
00186        "GBK",
00187        NULL
00188 };
00189 
00190 char *GB18030_names[] = {
00191        "GB18030",
00192        NULL
00193 };
00194 
00195 char *BIG5_names[] = {
00196        "BIG5",
00197        NULL
00198 };
00199 
00200 char *EUC_TW_names[] = {
00201        "EUC_TW",
00202        NULL
00203 };
00204 
00205 char *BIG5HK_names[] = {
00206        "BIG5HK",
00207        "BIG5HKSCS",
00208        NULL
00209 };
00210 
00211 char *EUC_TH_names[] = {
00212        "EUC_TH",
00213        NULL
00214 };
00215 
00216 char *EUC_KO_names[] = {
00217        "EUC_KO",
00218        NULL
00219 };
00220 
00221 char *UTF8_names[] = {
00222        "UTF-8",
00223        "UTF_8",
00224        "UTF8",
00225        NULL
00226 };
00227 
00228 /* supported locales for specified encode */
00229 char *GB2312_locales[] = {
00230        "zh_CN.EUC",
00231        "zh_CN",
00232        "zh",
00233        NULL
00234 };
00235 
00236 char *GBK_locales[] = {
00237        "zh_CN.GBK",
00238        "zh.GBK",
00239        NULL
00240 };
00241 
00242 char *GB18030_locales[] = {
00243        "zh_CN.GB18030",
00244        "zh_CN.UTF-8",
00245        "zh_CN.utf8",    /* for Linux */
00246        NULL
00247 };
00248 
00249 char *BIG5_locales[] = {
00250        "zh_TW.BIG5",
00251        "zh_TW.UTF-8",
00252        "zh_TW.utf8",    /* for Linux */
00253        "zh_TW",
00254        NULL
00255 };
00256 
00257 char *EUC_TW_locales[] = {
00258        "zh_TW.eucTW",
00259        "zh_TW.EUC",
00260        "zh_TW",
00261        NULL
00262 };
00263 
00264 char *BIG5HK_locales[] = {
00265        "zh_HK.big5hkscs",
00266        "zh_HK.BIG5HK",
00267        "zh_HK.UTF-8",
00268        "zh_HK.utf8",    /* for Linux */
00269        NULL
00270 };
00271 
00272 char *EUC_TH_locales[] = {
00273        "th_TH",
00274        "th_TH.TIS620",
00275        "th_TH.UTF-8",
00276        "th_TH.utf8",    /* for Linux */
00277        NULL
00278 };
00279 
00280 char *EUC_KO_locales[] = {
00281        "ko_KR.EUC",
00282        "ko_KR.UTF-8",
00283        "ko_KR.utf8",    /* for Linux */
00284        NULL
00285 };
00286 
00287 char *UTF8_locales[] = {
00288        "zh_TW.UTF-8",
00289        "zh_TW.utf8",    /* for Linux */
00290        "zh_HK.UTF-8",
00291        "zh_HK.utf8",    /* for Linux */
00292        NULL
00293 };
00294 
00295 /* iconv codeset name for specified encode */
00296 #define GB2312_CODESET_NAME        "GB2312"
00297 #define GBK_CODESET_NAME    "GBK"
00298 #define GB18030_CODESET_NAME       "GB18030"
00299 #define BIG5_CODESET_NAME   "BIG5"
00300 #define EUC_TW_CODESET_NAME "EUC-TW"
00301 #define BIG5HK_CODESET_NAME "BIG5-HKSCS"
00302 #define EUC_TH_CODESET_NAME "TIS620"
00303 #define EUC_KO_CODESET_NAME "EUC-KR"
00304 #define UTF8_CODESET_NAME   "UTF-8"
00305 
00306 /* unknown encode name */
00307 #define UNKNOWN_ENCODE             "UNKNOWN"
00308 
00309 Encode_Info  encode_info[ENCODES_NUM + 1] = {
00310        { 
00311               ENCODE_GB2312,
00312               GB2312_names,
00313               GB2312_locales,
00314               GB2312_CODESET_NAME,
00315               NULL,
00316               NULL,
00317        },
00318        { 
00319               ENCODE_GBK,
00320               GBK_names,
00321               GBK_locales,
00322               GBK_CODESET_NAME,
00323               NULL,
00324               NULL,
00325        },
00326        { 
00327               ENCODE_GB18030,
00328               GB18030_names,
00329               GB18030_locales,
00330               GB18030_CODESET_NAME,
00331               NULL,
00332               NULL,
00333        },
00334        { 
00335               ENCODE_BIG5,
00336               BIG5_names,
00337               BIG5_locales,
00338               BIG5_CODESET_NAME,
00339               NULL,
00340               NULL,
00341        },
00342        { 
00343               ENCODE_EUC_TW,
00344               EUC_TW_names,
00345               EUC_TW_locales,
00346               EUC_TW_CODESET_NAME,
00347               NULL,
00348               NULL,
00349        },
00350        { 
00351               ENCODE_BIG5HK,
00352               BIG5HK_names,
00353               BIG5HK_locales,
00354               BIG5HK_CODESET_NAME,
00355               NULL,
00356               NULL,
00357        },
00358        { 
00359               ENCODE_EUC_TH,
00360               EUC_TH_names,
00361               EUC_TH_locales,
00362               EUC_TH_CODESET_NAME,
00363               NULL,
00364               NULL,
00365        },
00366        {
00367               ENCODE_EUC_KO,
00368               EUC_KO_names,
00369               EUC_KO_locales,
00370               EUC_KO_CODESET_NAME,
00371               NULL,
00372               NULL,
00373        },
00374        { 
00375               ENCODE_UTF8,
00376               UTF8_names,
00377               UTF8_locales,
00378               UTF8_CODESET_NAME,
00379               NULL,
00380               NULL,
00381        }
00382 };
00383 
00384 iconv_t  fd_iconv_UTF8_to_UTF16 = NULL;
00385 iconv_t  fd_iconv_UTF16_to_UTF8 = NULL;
00386 
00387 char *get_langname_from_langid(int langid)
00388 {
00389        int ret = langid;
00390        
00391        if (langid < 0 || langid >= LANGS_NUM) 
00392               ret = 0;
00393 
00394        return(langgroup_info[ret].lang_name);
00395 }
00396 
00397 char *get_langname_from_locale(char *locale)
00398 {
00399        int lang_id, i, ret;
00400        char *s;
00401 
00402        ret = -1;
00403        for (lang_id = 0; lang_id < LANGS_NUM; lang_id++) {
00404               i = 0;
00405               while (1) {
00406                      s = langgroup_info[lang_id].support_locales[i];
00407                      if (!s || !*s) break;
00408                      if (!strcasecmp(s, locale)) {
00409                             ret = lang_id;
00410                             break;
00411                      }
00412                      i++;
00413               }
00414               if (ret != -1) break;
00415        }
00416 
00417        if (ret == -1) 
00418               ret = 0;
00419 
00420        return(langgroup_info[ret].lang_name);
00421 }
00422 
00423 char *get_langname_from_encodeid(int encodeid)
00424 {
00425        int lang_id, i, ret;
00426        int support_encode;
00427 
00428        ret = -1;
00429        for (lang_id = 0; lang_id < LANGS_NUM; lang_id++) {
00430               i = 0;
00431               while (1) {
00432                      support_encode = langgroup_info[lang_id].support_encodes[i];
00433                      if (support_encode == ENCODE_ERROR) break;
00434                      if (encodeid == support_encode) {
00435                             ret = lang_id;
00436                             break;
00437                      }
00438                      i++;
00439               }
00440               if (ret != -1) break;
00441        }
00442 
00443        if (ret == -1) 
00444               ret = 0;
00445 
00446        return(langgroup_info[ret].lang_name);
00447 }
00448 
00449 int get_langid_from_locale(char *locale)
00450 {
00451        int lang_id, i, ret;
00452        char *s;
00453 
00454        ret = -1;
00455        for (lang_id = 0; lang_id < LANGS_NUM; lang_id++) {
00456               i = 0;
00457               while (1) {
00458                      s = langgroup_info[lang_id].support_locales[i];
00459                      if (!s || !*s) break;
00460                      if (!strcasecmp(s, locale)) {
00461                             ret = lang_id;
00462                             break;
00463                      }
00464                      i++;
00465               }
00466               if (ret != -1) break;
00467        }
00468 
00469        if (ret == -1) 
00470               ret = 0;
00471 
00472        return(ret);
00473 }
00474 int get_langid_from_localeid(int localeid)
00475 {
00476        int lang_id, i, ret;
00477        int support_encode;
00478 
00479        ret = -1;
00480        for (lang_id = 0; lang_id < LANGS_NUM; lang_id++) {
00481               i = 0;
00482               while (1) {
00483                      support_encode = langgroup_info[lang_id].support_encodes[i];
00484                      if (support_encode == ENCODE_ERROR) break;
00485                      if (localeid == support_encode) {
00486                             ret = lang_id;
00487                             break;
00488                      }
00489                      i++;
00490               }
00491               if (ret != -1) break;
00492        }
00493 
00494        if (ret == -1) 
00495               ret = 0;
00496 
00497        return(ret);
00498 }
00499 
00500 int get_encodeid_from_name(char *name)
00501 {
00502        int encode_id, i, ret;
00503        char *s;
00504        
00505        ret = -1;
00506        for (encode_id = 0; encode_id < ENCODES_NUM; encode_id++) {
00507               i = 0;
00508               while (1) {
00509                      s = encode_info[encode_id].called_names[i];
00510                      if (!s || !*s) break;
00511                      if (!strcasecmp(s, name)) {
00512                             ret = encode_id;
00513                             break;
00514                      }
00515                      i++;
00516               }
00517               if (ret != -1) break;
00518        }
00519        if (ret == -1) ret = ENCODE_GB2312; /* return default encode */
00520        return(ret);  
00521 }
00522 
00523 int get_encodeid_from_locale(char *locale)
00524 {
00525        int encode_id, i, ret;
00526        char *s;
00527        
00528        ret = -1;
00529        for (encode_id = 0; encode_id < ENCODES_NUM; encode_id++) {
00530               i = 0;
00531               while (1) {
00532                      s = encode_info[encode_id].support_locales[i];
00533                      if (!s || !*s) break;
00534                      if (!strcasecmp(s, locale)) {
00535                             ret = encode_id;
00536                             break;
00537                      }
00538                      i++;
00539               }
00540               if (ret != -1) break;
00541        }
00542 
00543        if (ret == -1) ret = ENCODE_ERROR; /* return default encode */
00544 
00545        return(ret);  
00546 }
00547 
00548 char *get_name_from_encodeid(int encode_id)
00549 {
00550        if (encode_id >= 0 && encode_id <= ENCODES_NUM)
00551               return(encode_info[encode_id].called_names[0]);
00552        else
00553               return(NULL);
00554 }
00555 
00556 char *get_default_locale_from_locale(char *locale)
00557 {
00558        int encode_id, i, ret;
00559        char *s;
00560 
00561        ret = -1;
00562        for (encode_id = 0; encode_id < ENCODES_NUM; encode_id++) {
00563               i = 0;
00564               while (1) {
00565                      s = encode_info[encode_id].support_locales[i];
00566                      if (!s || !*s) break;
00567                      if (!strcasecmp(s, locale)) {
00568                             ret = encode_id;
00569                             break;
00570                      }
00571                      i++;
00572               }
00573               if (ret != -1) break;
00574        }
00575        
00576        if (ret == -1) return(NULL);
00577 
00578        return(encode_info[ret].support_locales[0]);
00579 }
00580 
00581 int  get_char_len_by_encodeid(int encode_id, unsigned char *ch_ptr)
00582 {
00583        int ret = 2;  /* default character length */
00584        unsigned char code0, code1;
00585 
00586        code0 = ch_ptr[0];
00587        if (code0 < 0x80) return(1);
00588 
00589        if (encode_id == ENCODE_UTF8) {
00590               if (code0 > 0xe0)           /* 3 bytes */
00591                      ret = 3;
00592        } else if (encode_id == ENCODE_GB18030) {
00593               code1 = ch_ptr[1];
00594               if (code0 >=0x81 && code0 <= 0xFE) {
00595                      if (code1 >= 0x30 && code1 <= 0x39)
00596                             ret = 4;
00597               } 
00598        } else if (encode_id == ENCODE_EUC_TW) {
00599               if (code0 == 0x8e)          /* 4 bytes */
00600                      ret = 4;
00601        } else if (encode_id == ENCODE_EUC_TH) {
00602               ret = 1;
00603        }
00604 
00605        return(ret);
00606 }
00607 
00608 int get_char_count_by_encodeid(int encode_id, unsigned char *ch_ptr, int *char_count)
00609 {
00610        int str_len = strlen((char *)ch_ptr);
00611        int str_pos = 0;
00612        int char_len;
00613        unsigned char *pStr;
00614 
00615        *char_count = 0;
00616        while (str_pos < str_len) {
00617               pStr = ch_ptr + str_pos;
00618               char_len = get_char_len_by_encodeid(encode_id, pStr);
00619               if (str_pos + char_len <= str_len) {
00620                      (*char_count)++;
00621                      str_pos += char_len;
00622               } else {
00623                      return(-1);
00624               }
00625        }
00626 
00627        return(0);
00628 }
00629 
00630 int is_valid_code(int encode_id, unsigned char *int_code, int code_len)
00631 {
00632        unsigned char code0, code1, code2, code3;
00633        
00634        code0 = int_code[0];
00635        code1 = int_code[1];
00636 
00637        switch (encode_id) {
00638               case ENCODE_GB2312:
00639                      if (code0 < 0xA1 || code0 > 0xFE)
00640                             return (-1);
00641                      if (code1 < 0xA1 || code1 > 0xFE)
00642                             return (-1);
00643                      break;
00644                      
00645               case ENCODE_GBK:
00646                      if (code0 < 0x81 || code0 > 0xFE)
00647                             return (-1);
00648                      if (code1 < 0x40 || code1 > 0xFE || code1 == 0x7F)
00649                             return (-1);
00650                      break;
00651 
00652               case ENCODE_GB18030:
00653                      if (code_len == 2) {
00654                             if (code0 < 0x81 || code0 > 0xFE)
00655                                    return (-1);
00656                             if (code1 < 0x40 || code1 > 0xFE || code1 == 0x7F)
00657                                    return (-1);
00658                      } else if (code_len == 4) {
00659                             code2 = int_code[2];
00660                             code3 = int_code[3];
00661                             if (code0 < 0x81 || code0 > 0xFE)
00662                                    return (-1);
00663                             if (code1 < 0x30 || code1 > 0x39)
00664                                    return (-1);
00665                             if (code2 < 0x81 || code2 > 0xFE)
00666                                    return (-1);
00667                             if (code3 < 0x30 || code3 > 0x39)
00668                                    return (-1);
00669                      }
00670                      break;
00671 
00672               case ENCODE_BIG5:
00673 #if 0
00674                      /* define in lcbig5.c */
00675                      if ((code0 >= 0xA1) && code0 <= 0xC5) || (code0 >= 0xC9 && code0 <= 0xF9)) {
00676                             if (code1 < 0x40 || code1 == 0xFF || (code1 >= 0x7F && code1 <= 0xA0))
00677                                    return (-1);
00678                             else
00679                                    return (0);
00680                      } else {
00681                             if (code0 == 0xC6 && (code1 >= 0x40 && code1 <= 0x7E))
00682                                    return (0);
00683                             else
00684                                    return (-1);
00685                      }
00686 #endif
00687                                    
00688                      if (code0 < 0xA1 || code0 > 0xFE)
00689                             return (-1);
00690                      if (code1 < 0x40 || code1 > 0xFE)
00691                             return (-1);
00692                      if (code1 > 0x7E && code1 < 0xA1)
00693                             return (-1);
00694                      break;
00695 
00696               case ENCODE_EUC_TW:
00697                      if (code_len == 2) {
00698                             if (code0 < 0x80 || code1 <0x80)
00699                                    return (-1);
00700                      } if (code_len == 4) {
00701                             code2 = int_code[2];
00702                             code3 = int_code[3];
00703                             if (code0 != 0x8E)
00704                                    return(-1);
00705                             if (code1 < 0x80 || code2 < 0x80 || code3 < 0x80)
00706                                    return(-1);
00707                      }
00708                      break;
00709 
00710               case ENCODE_BIG5HK:
00711                      if (code0 < 0x81 || code0 > 0xFE)
00712                             return (-1);
00713                      if (code1 < 0x40 || code1 > 0xFE)
00714                             return (-1);
00715                      break;
00716 
00717               case ENCODE_EUC_KO:
00718                      if (code0 < 0xA1 || code0 > 0xFE)
00719                             return (-1);
00720                      if (code1 < 0xA1 || code1 > 0xFE)
00721                             return (-1);
00722                      break;
00723 
00724               case ENCODE_UTF8:
00725                      break;
00726        }
00727        return(0);
00728 }
00729 
00730 int is_valid_encode_string(int encode_id, unsigned char *hzstr, int hzlen)
00731 {
00732        int i, char_len, ret;
00733        unsigned char *ptr;
00734 
00735        i = 0;
00736        while (i < hzlen) {
00737               ptr = hzstr + i;
00738               if (*ptr < 0x80) {
00739                      if (*ptr == 0x3f && i < hzlen-1) {
00740                             if (*(ptr+1) == 0x3f)
00741                                    return(-1);
00742                      }
00743 
00744                      i++;
00745               } else {
00746                      char_len = get_char_len_by_encodeid(encode_id, ptr);
00747                      ret = is_valid_code(encode_id, ptr, char_len);
00748                      if (ret == -1)
00749                             return(-1);
00750                      i += char_len;
00751               }
00752        }
00753 
00754        return (0);
00755 }
00756 
00757 /* iconv functions */
00758 int Convert_Native_To_UTF8(int encode_id, char *from_buf, size_t from_left,
00759                         char **to_buf, size_t * to_left)
00760 {
00761        char   *ip;
00762        char          *op;
00763        size_t        ileft, oleft;
00764        iconv_t              fd_iconv;
00765        char          *codeset;
00766        size_t        ret = 0;
00767        
00768        if (encode_id < 0 || encode_id >= ENCODES_NUM)
00769               return(-1);
00770 
00771        if ( (from_left < 0) || (*to_left < 0) )
00772               return(-1);
00773 
00774        ip = (char *) from_buf;
00775        ileft = from_left;
00776 
00777        op = *((char **) to_buf);
00778        oleft = *to_left;
00779 
00780        if (encode_id == ENCODE_UTF8) {
00781               if (ileft > oleft)
00782                      return(-1);
00783               memcpy(op, ip, ileft);
00784               *to_left = oleft - ileft;
00785               return(0);
00786        }
00787 
00788        fd_iconv = encode_info[encode_id].fd_iconv_to_utf8;
00789        if (fd_iconv == (iconv_t)-1) return(-1);
00790 
00791        if (fd_iconv == NULL) {
00792               codeset = encode_info[encode_id].iconv_codeset_name;
00793               fd_iconv = iconv_open("UTF-8", codeset);
00794               encode_info[encode_id].fd_iconv_to_utf8 = fd_iconv;
00795               if ( fd_iconv == (iconv_t) -1 )
00796                      return(-1);
00797        }
00798 
00799        ret = iconv(fd_iconv, &ip, &ileft, &op, &oleft);
00800        if (ret == -1) {
00801               return(-1);
00802        }
00803        *to_left = oleft;
00804        return(0);
00805 
00806 }
00807 
00808 int Convert_UTF8_To_Native(int encode_id, char *from_buf, size_t from_left,
00809                         char **to_buf, size_t * to_left)
00810 {
00811        char   *ip;
00812        char          *op;
00813        size_t        ileft, oleft;
00814        iconv_t              fd_iconv;
00815        char          *codeset;
00816        size_t        ret = 0;
00817        
00818        if (encode_id < 0 || encode_id >= ENCODES_NUM)
00819               return(-1);
00820 
00821        if ( (from_left < 0) || (*to_left < 0) )
00822               return(-1);
00823 
00824        ip = (char *) from_buf;
00825        ileft = from_left;
00826 
00827        op = *((char **) to_buf);
00828        oleft = *to_left;
00829 
00830        if (encode_id == ENCODE_UTF8) {
00831               if (ileft > oleft)
00832                      return(-1);
00833               memcpy(op, ip, ileft);
00834               *to_left = oleft - ileft;
00835               return(0);
00836        }
00837 
00838        fd_iconv = encode_info[encode_id].fd_iconv_from_utf8;
00839        if (fd_iconv == (iconv_t)-1) return(-1);
00840 
00841        if (fd_iconv == NULL) {
00842               codeset = encode_info[encode_id].iconv_codeset_name;
00843               fd_iconv = iconv_open(codeset, "UTF-8");
00844               encode_info[encode_id].fd_iconv_from_utf8 = fd_iconv;
00845               if ( fd_iconv == (iconv_t) -1 )
00846                      return(-1);
00847        }
00848 
00849        ret = iconv(fd_iconv, &ip, &ileft, &op, &oleft);
00850        if (ret == -1) {
00851               return(-1);
00852        }
00853        *to_left = oleft;
00854        return(0);
00855 }
00856 
00857 #define UTF16_STRLEN    1024
00858        
00859 int Convert_Native_To_UTF16(int encode_id, char *from_buf, size_t from_left,
00860                         char **to_buf, size_t *to_left)
00861 {
00862        char   *ip;
00863        char          *op;
00864        size_t        ileft, oleft;
00865 
00866        char          *codeset;
00867        iconv_t              fd_iconv_native_to_utf8;
00868 
00869        size_t        ret = 0;
00870        int           skip_native_to_utf8_iconv = 0;
00871 
00872        if (encode_id < 0 || encode_id >= ENCODES_NUM)
00873               return(-1);
00874 
00875        if ( (from_left < 0) || (*to_left < 0) )
00876               return(-1);
00877 
00878        /* Initialize the iconv of utf8_to_ucs2 */
00879        if (fd_iconv_UTF8_to_UTF16 == (iconv_t)-1 )
00880                return(-1);
00881 
00882        if (fd_iconv_UTF8_to_UTF16 == NULL) {
00883               fd_iconv_UTF8_to_UTF16 = iconv_open("UTF-16", "UTF-8");
00884               if (fd_iconv_UTF8_to_UTF16 == (iconv_t)-1 )
00885                      return(-1);
00886        }
00887 
00888        if (encode_id == ENCODE_UTF8)
00889               skip_native_to_utf8_iconv = 1;
00890 
00891        ip = (char *) from_buf;
00892        ileft = from_left;
00893 
00894        op = *((char **) to_buf);
00895        oleft = *to_left;
00896 
00897        if (!skip_native_to_utf8_iconv) {
00898               char          buffer[UTF16_STRLEN];   /* Fix me! */
00899               const size_t  buf_len = UTF16_STRLEN;
00900               char          *src, *dst;
00901               size_t        src_len, dst_len;
00902 
00903               /* Initialize the iconv of native_to_utf8 */
00904               fd_iconv_native_to_utf8 = encode_info[encode_id].fd_iconv_to_utf8;
00905               if (fd_iconv_native_to_utf8 == (iconv_t)-1) return(-1);
00906 
00907               if (fd_iconv_native_to_utf8 == NULL) {
00908                      codeset = encode_info[encode_id].iconv_codeset_name;
00909                      fd_iconv_native_to_utf8 = iconv_open("UTF-8", codeset);
00910                      encode_info[encode_id].fd_iconv_to_utf8 = fd_iconv_native_to_utf8;
00911                      if ( fd_iconv_native_to_utf8 == (iconv_t) -1 )
00912                             return(-1);
00913               }
00914 
00915               while ((ileft > 0) && (oleft > 0)) {
00916                      dst = buffer;
00917                      dst_len = buf_len;
00918                      ret = iconv(fd_iconv_native_to_utf8, &ip, &ileft, (char **) &dst, &dst_len);
00919                      if (ret == -1) {
00920                             return(-1);
00921                      }
00922                      src = buffer;
00923                      src_len = buf_len - dst_len;
00924                      ret = iconv(fd_iconv_UTF8_to_UTF16, (char **) &src, &src_len, &op, &oleft);
00925                      if (ret == -1) {
00926                             return(-1);
00927                      }
00928               }
00929 
00930        } else {
00931               ret = iconv(fd_iconv_UTF8_to_UTF16, &ip, &ileft, &op, &oleft);
00932               if (ret == -1) {
00933                       return(-1);
00934               }
00935        }
00936 
00937        if (0xFEFF == **((CARD16 **) to_buf)) {
00938               memmove(*to_buf, *to_buf + 2, *to_left - oleft - 2);
00939               *to_left = (oleft + 2);
00940        } else {
00941               *to_left = oleft;
00942        }
00943 
00944        return(0);
00945 }
00946 
00947 int Convert_UTF16_To_Native(int encode_id, char *from_buf, size_t from_left,
00948                         char **to_buf, size_t * to_left)
00949 {
00950        char   *ip;
00951        char          *op;
00952        size_t        ileft, oleft;
00953        char          *codeset;
00954        iconv_t              fd_iconv_utf8_to_native;
00955 
00956        size_t        ret = 0;
00957        int           skip_utf8_to_native_iconv = 0;
00958 
00959        if (encode_id < 0 || encode_id >= ENCODES_NUM)
00960               return(-1);
00961 
00962        if ( (from_left < 0) || (*to_left < 0) )
00963               return(-1);
00964 
00965        /* Initialize the iconv of utf8_to_ucs2 */
00966        if (fd_iconv_UTF16_to_UTF8 == (iconv_t)-1 )
00967                return(-1);
00968 
00969        if (fd_iconv_UTF16_to_UTF8 == NULL) {
00970               fd_iconv_UTF16_to_UTF8 = iconv_open("UTF-8", "UTF-16");
00971               if (fd_iconv_UTF16_to_UTF8 == (iconv_t)-1 )
00972                      return(-1);
00973        }
00974 
00975        if (encode_id == ENCODE_UTF8)
00976               skip_utf8_to_native_iconv = 1;
00977 
00978        ip = (char *) from_buf;
00979        ileft = from_left;
00980 
00981        op = *((char **) to_buf);
00982        oleft = *to_left;
00983 
00984        if (!skip_utf8_to_native_iconv) {
00985               char          buffer[UTF16_STRLEN];   /* Fix me! */
00986               const size_t  buf_len = UTF16_STRLEN;
00987               char          *src, *dst;
00988               size_t        src_len, dst_len;
00989 
00990               /* Initialize the iconv of native_to_utf8 */
00991               fd_iconv_utf8_to_native = encode_info[encode_id].fd_iconv_from_utf8;
00992               if (fd_iconv_utf8_to_native == (iconv_t)-1) return(-1);
00993 
00994               if (fd_iconv_utf8_to_native == NULL) {
00995                      codeset = encode_info[encode_id].iconv_codeset_name;
00996                      fd_iconv_utf8_to_native = iconv_open(codeset, "UTF-8");
00997                      encode_info[encode_id].fd_iconv_from_utf8 = fd_iconv_utf8_to_native;
00998                      if ( fd_iconv_utf8_to_native == (iconv_t) -1 )
00999                             return(-1);
01000               }
01001 
01002               while ((ileft > 0) && (oleft > 0)) {
01003                      dst = buffer;
01004                      dst_len = buf_len;
01005                      ret = iconv(fd_iconv_UTF16_to_UTF8, &ip, &ileft, (char **) &dst, &dst_len);
01006                      if (ret == -1) {
01007                             return(-1);
01008                      }
01009                      src = buffer;
01010                      src_len = buf_len - dst_len;
01011                      ret = iconv(fd_iconv_utf8_to_native, (char **) &src, &src_len, &op, &oleft);
01012                      if (ret == -1) {
01013                             return(-1);
01014                      }
01015               }
01016 
01017        } else {
01018               ret = iconv(fd_iconv_UTF16_to_UTF8, &ip, &ileft, &op, &oleft);
01019               if (ret == -1) {
01020                       return(-1);
01021               }
01022        }
01023 
01024        *to_left = oleft;
01025 
01026        return(0);
01027 }