home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libi18n / ucs2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  45.8 KB  |  1,750 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /*----------------------------------------------------------------------------
  19.  
  20.     Function UCS2ToValueAndInfo
  21.     
  22. ----------------------------------------------------------------------------*/
  23. #include "intlpriv.h"
  24.  
  25. #include "ugen.h"
  26. #include "umap.h"
  27. #include "csid.h"
  28. #include "xp_mem.h"
  29. #include "xpassert.h"
  30. #include "unicpriv.h"
  31. #include "libi18n.h"
  32. #if defined(XP_WIN) || defined(XP_OS2)
  33. #include "prlink.h"
  34. #endif
  35.  
  36.  
  37.  
  38. /*    
  39.     The following table is moved from npc.c npctocsid[] I rename it and try to get ride of npc.c
  40. */
  41. PRIVATE int16    csidtable[MAXCSIDINTBL] =
  42. {
  43.     CS_DEFAULT,        CS_ASCII,        CS_LATIN1,        CS_JIS,            /*  0 -  3 */
  44.     CS_SJIS,        CS_EUCJP,        CS_MAC_ROMAN,    CS_BIG5,        /*  4 -  7 */ 
  45.     CS_GB_8BIT,        CS_CNS_8BIT,    CS_LATIN2,        CS_MAC_CE,        /*  8 - 11 */ 
  46.     CS_KSC_8BIT,    CS_2022_KR,     CS_8859_3,        CS_8859_4,        /* 12 - 15 */
  47.     CS_8859_5,        CS_8859_6,        CS_8859_7,        CS_8859_8,        /* 16 - 19 */
  48.     CS_8859_9,        CS_SYMBOL,        CS_DINGBATS,    CS_DECTECH,        /* 20 - 23 */
  49.     CS_CNS11643_1,    CS_CNS11643_2,    CS_JISX0208,    CS_JISX0201,    /* 24 - 27 */
  50.     CS_KSC5601,        CS_TIS620,        CS_JISX0212,    CS_GB2312,        /* 28 - 31 */
  51.     CS_UNKNOWN,        CS_UNKNOWN,        CS_UNKNOWN,        CS_UNKNOWN,        /* 32 - 35 */
  52.     CS_UNKNOWN,        CS_X_BIG5,        CS_UNKNOWN,        CS_KOI8_R,        /* 36 - 39 */
  53.     CS_MAC_CYRILLIC,CS_CP_1251,        CS_MAC_GREEK,    CS_CP_1253,        /* 40 - 43 */
  54.     CS_CP_1250,        CS_CP_1254,        CS_MAC_TURKISH,    CS_UNKNOWN,        /* 44 - 47 */
  55.     CS_UNKNOWN,        CS_UNKNOWN,        CS_UNKNOWN,        CS_UNKNOWN,        /* 48 - 51 */
  56.     CS_UNKNOWN,        CS_CP_850,        CS_CP_852,        CS_CP_855,        /* 52 - 55 */
  57.     CS_CP_857,        CS_CP_862,        CS_CP_864,        CS_CP_866,        /* 56 - 59 */
  58.     CS_CP_874,        CS_CP_1257,        CS_CP_1258,        CS_UNKNOWN,        /* 60 - 63 */    
  59. };
  60.  
  61. #define intl_GetValidCSID(fb)    (csidtable[(fb) & (MAXCSIDINTBL - 1)])
  62.  
  63. /*
  64.     Our global table are deivded into 256 row
  65.     each row have 256 entries
  66.     each entry have one value and one info
  67.     Info field contains csid index
  68. */
  69.  
  70. typedef struct {
  71.     uint16 value[256];
  72.     unsigned char info[256];
  73. } uRowTable;
  74.  
  75. PRIVATE uRowTable *uRowTablePtArray[256];
  76.  
  77. PRIVATE uTable*     LoadToUCS2Table(uint16 csid);
  78. PRIVATE void     UnloadToUCS2Table(uint16 csid, uTable *utblPtr);
  79. PRIVATE uTable*     LoadFromUCS2Table(uint16 csid);
  80. PRIVATE void     UnloadFromUCS2Table(uint16 csid, uTable *utblPtr);
  81. PRIVATE void     CheckAndAddEntry(uint16 ucs2, uint16 med , uint16 csid);
  82. PRIVATE XP_Bool     UCS2ToValueAndInfo(uint16 ucs2, uint16* med, unsigned char* info);
  83. PRIVATE void     InitUCS2Table(void);
  84.  
  85. /*    
  86.     UCS2 Table- is build into the navigator
  87. */
  88. PRIVATE uint16 Ucs2Tbl[] = {
  89.     0x0001,    0x0004,    0x0005,    0x0008,    0x0000, 0x0000, 0xFFFF, 0x0000
  90. };
  91. PRIVATE uint16 asciiTbl[] = {
  92.     0x0001,    0x0004,    0x0005,    0x0008,    0x0000, 0x0000, 0x007F, 0x0000
  93. };
  94.  
  95. #ifdef XP_UNIX
  96.  
  97. /*    Currently, we only support the Latin 1 and Japanese Table. */
  98. /*  We will add more table here after the first run */
  99. /*--------------------------------------------------------------------------*/
  100. /*    Latin stuff */
  101. PRIVATE uint16 iso88591FromTbl[] = {
  102. #include "8859-1.uf"
  103. };
  104. PRIVATE uint16 iso88591ToTbl[] = {
  105. #include "8859-1.ut"
  106. };
  107. /*--------------------------------------------------------------------------*/
  108. /*    Japanese stuff */
  109. PRIVATE uint16 JIS0208FromTbl[] = {
  110. #include "jis0208.uf"
  111. };
  112. PRIVATE uint16 JIS0208ToTbl[] = {
  113. #include "jis0208.ut"
  114. };
  115. PRIVATE uint16 JIS0201FromTbl[] = {
  116. #include "jis0201.uf"
  117. };
  118. PRIVATE uint16 JIS0201ToTbl[] = {
  119. #include "jis0201.ut"
  120. };
  121. PRIVATE uint16 JIS0212FromTbl[] = {
  122. #include "jis0212.uf"
  123. };
  124. PRIVATE uint16 JIS0212ToTbl[] = {
  125. #include "jis0212.ut"
  126. };
  127. PRIVATE uint16 SJISFromTbl[] = {
  128. #include "sjis.uf"
  129. };
  130. PRIVATE uint16 SJISToTbl[] = {
  131. #include "sjis.ut"
  132. };
  133.  
  134. /*--------------------------------------------------------------------------*/
  135. /*    Latin2 Stuff */
  136. PRIVATE uint16 iso88592FromTbl[] = {
  137. #include "8859-2.uf"
  138. };
  139. PRIVATE uint16 iso88592ToTbl[] = {
  140. #include "8859-2.ut"
  141. };
  142. /*--------------------------------------------------------------------------*/
  143. /*    Traditional Chinese Stuff */
  144. PRIVATE uint16 CNS11643_1FromTbl[] = {
  145. #include "cns_1.uf"
  146. };
  147. PRIVATE uint16 CNS11643_1ToTbl[] = {
  148. #include "cns_1.ut"
  149. };
  150. PRIVATE uint16 CNS11643_2FromTbl[] = {
  151. #include "cns_2.uf"
  152. };
  153. PRIVATE uint16 CNS11643_2ToTbl[] = {
  154. #include "cns_2.ut"
  155. };
  156. PRIVATE uint16 Big5FromTbl[] = {
  157. #include "big5.uf"
  158. };
  159. PRIVATE uint16 Big5ToTbl[] = {
  160. #include "big5.ut"
  161. };
  162. /*--------------------------------------------------------------------------*/
  163. /*    Simplified Chinese Stuff */
  164. PRIVATE uint16 GB2312FromTbl[] = {
  165. #include "gb2312.uf"
  166. };
  167. PRIVATE uint16 GB2312ToTbl[] = {
  168. #include "gb2312.ut"
  169. };
  170. /*--------------------------------------------------------------------------*/
  171. /*    Korean Stuff */
  172. #ifdef UNICODE_1_1_BASE_KOREAN    
  173.  
  174. PRIVATE uint16 KSC5601FromTbl[] = {
  175. #include "ksc5601.uf"
  176. };
  177. PRIVATE uint16 KSC5601ToTbl[] = {
  178. #include "ksc5601.ut"
  179. };
  180.  
  181. #else /* UNICODE_1_1_BASE_KOREAN    */
  182.  
  183. /*    
  184.     For UNIX the Korean UNICODE 2.0 table is u20kscgl.u[tf]
  185.     They are GL base table that contains minimun set of Korean table that
  186.     the UNIX actually can handle.
  187. */
  188. PRIVATE uint16 KSC5601FromTbl[] = {
  189. #include "u20kscgl.uf"            
  190. };
  191. PRIVATE uint16 KSC5601ToTbl[] = {
  192. #include "u20kscgl.ut"
  193. };
  194.  
  195. #endif /* UNICODE_1_1_BASE_KOREAN    */
  196.  
  197.  
  198. /*--------------------------------------------------------------------------*/
  199. /*    Symbol Stuff */
  200. PRIVATE uint16 SymbolFromTbl[] = {
  201. #include "macsymbo.uf"
  202. };
  203. PRIVATE uint16 SymbolToTbl[] = {
  204. #include "macsymbo.ut"
  205. };
  206.  
  207. /*--------------------------------------------------------------------------*/
  208. /*    Dingbats Stuff */
  209. PRIVATE uint16 DingbatsFromTbl[] = {
  210. #include "macdingb.uf"
  211. };
  212. PRIVATE uint16 DingbatsToTbl[] = {
  213. #include "macdingb.ut"
  214. };
  215. /*--------------------------------------------------------------------------*/
  216. PRIVATE uTable* LoadToUCS2Table(uint16 csid)
  217. {
  218.     switch(csid) {
  219.     case CS_ASCII:
  220.         return (uTable*) asciiTbl;
  221.         
  222.     /*    Latin stuff */
  223.     case CS_LATIN1:
  224.         return (uTable*) iso88591ToTbl;
  225.         
  226.     /*    Japanese */
  227.     case CS_JISX0208:
  228.         return (uTable*) JIS0208ToTbl;
  229.  
  230.     case CS_JISX0201:
  231.         return (uTable*) JIS0201ToTbl;
  232.  
  233.     case CS_JISX0212:
  234.         return (uTable*) JIS0212ToTbl;
  235.     case CS_SJIS:
  236.         return (uTable*) SJISToTbl;
  237.  
  238.     /*    Latin2 Stuff */
  239.     case CS_LATIN2:
  240.         return (uTable*) iso88592ToTbl;
  241.     /*    Traditional Chinese Stuff */
  242.     case CS_CNS11643_1:
  243.         return (uTable*) CNS11643_1ToTbl;
  244.     case CS_CNS11643_2:
  245.         return (uTable*) CNS11643_2ToTbl;
  246.     case CS_BIG5:
  247.     case CS_X_BIG5:
  248.         return (uTable*) Big5ToTbl;
  249.  
  250.  
  251.     /*    Simplified Chinese Stuff */
  252.     case CS_GB2312:
  253.     case CS_GB_8BIT:
  254.         return (uTable*) GB2312ToTbl;
  255.  
  256.     /*    Korean Stuff */
  257.     case CS_KSC5601:
  258.     case CS_KSC_8BIT:
  259.         return (uTable*) KSC5601ToTbl;
  260.  
  261.     /*    Symbol Stuff */
  262.     case CS_SYMBOL:
  263.         return (uTable*) SymbolToTbl;
  264.  
  265.     /*    Dingbats Stuff */
  266.     case CS_DINGBATS:
  267.         return (uTable*) DingbatsToTbl;
  268.  
  269.     /*    UTF8 */
  270.     case CS_UTF8:
  271.     case CS_UCS2:
  272.         return (uTable*) Ucs2Tbl;
  273.  
  274.     /*    Other Stuff */
  275.     default:
  276.         XP_ASSERT(TRUE);
  277.         return NULL;
  278.     }
  279. }
  280. PRIVATE uTable* LoadFromUCS2Table(uint16 csid)
  281. {
  282.     switch(csid) {
  283.     case CS_ASCII:
  284.         return (uTable*) asciiTbl;
  285.         
  286.     /*    Latin stuff */
  287.     case CS_LATIN1:
  288.         return (uTable*) iso88591FromTbl;
  289.         
  290.     /*    Japanese */
  291.     case CS_JISX0208:
  292.         return (uTable*) JIS0208FromTbl;
  293.  
  294.     case CS_JISX0201:
  295.         return (uTable*) JIS0201FromTbl;
  296.  
  297.     case CS_JISX0212:
  298.         return (uTable*) JIS0212FromTbl;
  299.  
  300.     case CS_SJIS:
  301.         return (uTable*) SJISFromTbl;
  302.  
  303.     /*    Latin2 Stuff */
  304.     case CS_LATIN2:
  305.         return (uTable*) iso88592FromTbl;
  306.     /*    Traditional Chinese Stuff */
  307.     case CS_CNS11643_1:
  308.         return (uTable*) CNS11643_1FromTbl;
  309.     case CS_CNS11643_2:
  310.         return (uTable*) CNS11643_2FromTbl;
  311.     case CS_X_BIG5:
  312.     case CS_BIG5:
  313.         return (uTable*) Big5FromTbl;
  314.  
  315.  
  316.     /*    Simplified Chinese Stuff */
  317.     case CS_GB2312:
  318.     case CS_GB_8BIT:
  319.         return (uTable*) GB2312FromTbl;
  320.  
  321.     /*    Korean Stuff */
  322.     case CS_KSC5601:
  323.     case CS_KSC_8BIT:
  324.         return (uTable*) KSC5601FromTbl;
  325.  
  326.     /*    Symbol Stuff */
  327.     case CS_SYMBOL:
  328.         return (uTable*) SymbolFromTbl;
  329.  
  330.     /*    Dingbats Stuff */
  331.     case CS_DINGBATS:
  332.         return (uTable*) DingbatsFromTbl;
  333.  
  334.     /*    UTF8 */
  335.     case CS_UTF8:
  336.     case CS_UCS2:
  337.         return (uTable*) Ucs2Tbl;
  338.  
  339.         /*    Other Stuff */
  340.     default:
  341.         XP_ASSERT(TRUE);
  342.         return NULL;
  343.     }
  344. }
  345.  
  346. /*--------------------------------------------------------------------------*/
  347. /*--------------------------------------------------------------------------*/
  348. PRIVATE void UnloadToUCS2Table(uint16 csid, uTable *utblPtr)
  349. {
  350.     /* If we link those table in our code. We don't need to do anything to 
  351.         unload them */
  352. }
  353. /*--------------------------------------------------------------------------*/
  354. /*--------------------------------------------------------------------------*/
  355. PRIVATE void UnloadFromUCS2Table(uint16 csid, uTable *utblPtr)
  356. {
  357.     /* If we link those table in our code. We don't need to do anything to 
  358.         unload them */
  359. }
  360.  
  361. #endif /* XP_UNIX */
  362.  
  363. #ifdef XP_MAC
  364. PRIVATE XP_Bool isIcelandicRoman()
  365. {
  366.     static int region = -1;
  367.     if(region == -1)
  368.     {
  369.         region = GetScriptManagerVariable(smRegionCode);
  370.     }
  371.     return (verIceland == region);
  372. }
  373. /*--------------------------------------------------------------------------*/
  374. /*--------------------------------------------------------------------------*/
  375. PRIVATE uTable* LoadUCS2Table(uint16 csid,int from)
  376. {
  377.     /* We need to add reference count here */
  378.     Handle tableHandle;
  379.     switch(csid)
  380.     {
  381.         case CS_ASCII:
  382.             return (uTable*) asciiTbl;
  383.             break;
  384.         case CS_UCS2:
  385.         case CS_UTF8:
  386.             return (uTable*) Ucs2Tbl;
  387.             break;
  388.         case CS_MAC_ROMAN:
  389.         /* Handle MacRoman Variant here */
  390.             if(isIcelandicRoman())
  391.                 csid = CS_MAC_ROMAN | 0x1000; /* if this is Icelandic variant */
  392.             break;
  393.         default: 
  394.             break;
  395.     }
  396.     tableHandle = GetResource((from ? 'UFRM' : 'UTO '), csid);
  397.     if(tableHandle == NULL || ResError()!=noErr)
  398.         return NULL;
  399.     if(*tableHandle == NULL)
  400.         LoadResource(tableHandle);
  401.     HNoPurge(tableHandle);
  402.     HLock(tableHandle);
  403.     return((uTable*) *tableHandle);
  404. }
  405. /*--------------------------------------------------------------------------*/
  406. /*--------------------------------------------------------------------------*/
  407. PRIVATE void UnloadUCS2Table(uint16 csid, uTable *utblPtr, int from)
  408. {
  409.     /* We need to add reference count here */
  410.     Handle tableHandle;
  411.     switch(csid)
  412.     {
  413.         case CS_ASCII:
  414.         case CS_UCS2:
  415.         case CS_UTF8:
  416.             return;
  417.         case CS_MAC_ROMAN:
  418.         /* Handle MacRoman Variant here */
  419.             if(isIcelandicRoman())
  420.                 csid = CS_MAC_ROMAN | 0x1000; /* if this is Icelandic variant */
  421.             break;
  422.         default: 
  423.             break;
  424.     }
  425.     tableHandle = GetResource((from ? 'UFRM' : 'UTO '), csid);
  426.     if(tableHandle == NULL || ResError()!=noErr)
  427.         return;
  428.     HUnlock((Handle) tableHandle);
  429.     HPurge(tableHandle);
  430. }
  431. /*--------------------------------------------------------------------------*/
  432. /*--------------------------------------------------------------------------*/
  433. PRIVATE uTable* LoadToUCS2Table(uint16 csid)
  434. {
  435.     return LoadUCS2Table(csid, FALSE);
  436. }
  437. /*--------------------------------------------------------------------------*/
  438. /*--------------------------------------------------------------------------*/
  439. PRIVATE void UnloadToUCS2Table(uint16 csid, uTable *utblPtr)
  440. {
  441.     UnloadUCS2Table(csid, utblPtr, FALSE);
  442. }
  443. /*--------------------------------------------------------------------------*/
  444. /*--------------------------------------------------------------------------*/
  445. PRIVATE uTable* LoadFromUCS2Table(uint16 csid)
  446. {
  447.     return LoadUCS2Table(csid, TRUE);
  448. }
  449. /*--------------------------------------------------------------------------*/
  450. /*--------------------------------------------------------------------------*/
  451. PRIVATE void UnloadFromUCS2Table(uint16 csid, uTable *utblPtr)
  452. {
  453.     UnloadUCS2Table(csid, utblPtr, TRUE);
  454. }
  455. #endif /* XP_MAC */
  456.  
  457. #if defined(XP_WIN)
  458.  
  459. #ifdef XP_WIN32
  460. #define UNICODEDLL "UNI3200.DLL"
  461. #define LIBRARYLOADOK(l)    (l != NULL)
  462. #define UNICODE_LOADUCS2TABLE_SYM    "UNICODE_LOADUCS2TABLE"
  463. #define UNICODE_UNLOADUCS2TABLE_SYM    "UNICODE_UNLOADUCS2TABLE"
  464. #else
  465. #define UNICODEDLL "UNI1600.DLL"
  466. #define LIBRARYLOADOK(l)    (l >= 32)
  467. #define UNICODE_LOADUCS2TABLE_SYM    "_UNICODE_LOADUCS2TABLE"
  468. #define UNICODE_UNLOADUCS2TABLE_SYM    "_UNICODE_UNLOADUCS2TABLE"
  469. #endif    /* !XP_WIN32 */
  470.  
  471. PRLibrary* uniLib = NULL;
  472.  
  473. PRIVATE uTable* LoadUCS2Table(uint16 csid, int from)
  474. {
  475.     uTable* ret = NULL;
  476.     switch(csid)
  477.     {
  478.         case CS_ASCII:
  479.             ret = (uTable*) asciiTbl;
  480.             break;
  481.         case CS_UCS2:
  482.         case CS_UTF8:
  483.             ret = (uTable*) Ucs2Tbl;
  484.             break;
  485.         default:
  486.             if(uniLib == NULL )
  487.                 uniLib = PR_LoadLibrary(UNICODEDLL);
  488.             if(uniLib)
  489.             {
  490.                 typedef uTable* (*f) (uint16 i1, int i2);
  491.                 static f p = NULL;
  492.  
  493.                                 if (p == NULL) {
  494. #ifndef NSPR20
  495.                     p = (f)PR_FindSymbol(UNICODE_LOADUCS2TABLE_SYM, uniLib);
  496. #else
  497.                     p = (f)PR_FindSymbol(uniLib, UNICODE_LOADUCS2TABLE_SYM);
  498. #endif
  499.                                 }
  500.                 XP_ASSERT(p);
  501.                 if(p)
  502.                     ret = (*p)(csid, from);
  503.             }
  504.             break;
  505.     }
  506.     return ret;
  507. }
  508. PRIVATE void UnloadUCS2Table(uint16 csid, uTable* utblPtr, int from)
  509. {
  510.     switch(csid)
  511.     {
  512.         case CS_ASCII:
  513.         case CS_UCS2:
  514.         case CS_UTF8:
  515.             break;
  516.         default:
  517.             if(uniLib == NULL )
  518.                 uniLib = PR_LoadLibrary(UNICODEDLL);
  519.             if(uniLib)
  520.             {
  521.                 typedef void (*f) (uint16 i1, uTable* i2, int i3);
  522.                 static f p = NULL;
  523.  
  524.                                 if (p == NULL) {
  525. #ifndef NSPR20
  526.                     p = (f)PR_FindSymbol(UNICODE_UNLOADUCS2TABLE_SYM, uniLib);
  527. #else
  528.                     p = (f)PR_FindSymbol(uniLib, UNICODE_UNLOADUCS2TABLE_SYM);
  529. #endif
  530.                                 }
  531.                 XP_ASSERT(p);
  532.                 if(p)
  533.                     (*p)(csid, utblPtr, from);
  534.             }
  535.         break;
  536.     }
  537. }
  538. PRIVATE uTable* LoadToUCS2Table(uint16 csid)
  539. {
  540.     return(LoadUCS2Table(csid,0));
  541. }
  542. PRIVATE void UnloadToUCS2Table(uint16 csid, uTable *utblPtr)
  543. {
  544.     UnloadUCS2Table(csid, utblPtr, 0);
  545. }
  546. PRIVATE uTable* LoadFromUCS2Table(uint16 csid)
  547. {
  548.     return(LoadUCS2Table(csid,1));
  549. }
  550. PRIVATE void UnloadFromUCS2Table(uint16 csid, uTable *utblPtr)
  551. {
  552.     UnloadUCS2Table(csid, utblPtr, 1);
  553. }
  554. #endif /* XP_WIN */
  555.  
  556.  
  557. #ifdef XP_OS2
  558. /*
  559.  * The basic design for OS/2 is to place all of the tables inline.
  560.  * Since we reference most of the from tables during init to form
  561.  * the row tables, we might as well just put them here.
  562.  */
  563.  
  564. /*    
  565.  * Latin 1 
  566.  */
  567. PRIVATE uint16 cp1252FromTbl[] = {
  568. #include "cp1252.uf"
  569. };
  570. PRIVATE uint16 cp1252ToTbl[] = {
  571. #include "cp1252.ut"
  572. };
  573. /*    
  574.  * Latin 2 
  575.  */
  576. PRIVATE uint16 iso8859_2FromTbl[] = {
  577. #include "8859-2.uf"
  578. };
  579. PRIVATE uint16 iso8859_2ToTbl[] = {
  580. #include "8859-2.ut"
  581. };
  582. /*    
  583.  * Japan
  584.  */
  585. PRIVATE uint16 japanFromTbl[] = {
  586. #include "sjis.uf"
  587. };
  588. PRIVATE uint16 japanToTbl[] = {
  589. #include "sjis.ut"
  590. };
  591. /*    
  592.  * China (may need update for GBK)
  593.  */
  594. PRIVATE uint16 chinaFromTbl[] = {
  595. #include "gb2312.uf"
  596. };
  597. PRIVATE uint16 chinaToTbl[] = {
  598. #include "gb2312.ut"
  599. };
  600. /*    
  601.  * Taiwan
  602.  */
  603. PRIVATE uint16 taiwanFromTbl[] = {
  604. #include "big5.uf"
  605. };
  606. PRIVATE uint16 taiwanToTbl[] = {
  607. #include "big5.ut"
  608. };
  609.  
  610. /*    
  611.  * ISO Codepages
  612.  */
  613. PRIVATE uint16 iso8859_3FromTbl[] = {
  614. #include "8859-3.uf"
  615. };
  616. PRIVATE uint16 iso8859_3ToTbl[] = {
  617. #include "8859-3.ut"
  618. };
  619. PRIVATE uint16 iso8859_4FromTbl[] = {
  620. #include "8859-4.uf"
  621. };
  622. PRIVATE uint16 iso8859_4ToTbl[] = {
  623. #include "8859-4.ut"
  624. };
  625. PRIVATE uint16 iso8859_5FromTbl[] = {
  626. #include "8859-5.uf"
  627. };
  628. PRIVATE uint16 iso8859_5ToTbl[] = {
  629. #include "8859-5.ut"
  630. };
  631. PRIVATE uint16 iso8859_6FromTbl[] = {
  632. #include "8859-6.uf"
  633. };
  634. PRIVATE uint16 iso8859_6ToTbl[] = {
  635. #include "8859-6.ut"
  636. };
  637. PRIVATE uint16 iso8859_7FromTbl[] = {
  638. #include "8859-7.uf"
  639. };
  640. PRIVATE uint16 iso8859_7ToTbl[] = {
  641. #include "8859-7.ut"
  642. };
  643. PRIVATE uint16 iso8859_8FromTbl[] = {
  644. #include "8859-8.uf"
  645. };
  646. PRIVATE uint16 iso8859_8ToTbl[] = {
  647. #include "8859-8.ut"
  648. };
  649. PRIVATE uint16 iso8859_9FromTbl[] = {
  650. #include "8859-9.uf"
  651. };
  652. PRIVATE uint16 iso8859_9ToTbl[] = {
  653. #include "8859-9.ut"
  654. };
  655.  
  656. /*    
  657.  * Windows Codepages
  658.  */
  659. PRIVATE uint16 cp1250FromTbl[] = {
  660. #include "cp1250.uf"
  661. };
  662. PRIVATE uint16 cp1250ToTbl[] = {
  663. #include "cp1250.ut"
  664. };
  665. PRIVATE uint16 cp1251FromTbl[] = {
  666. #include "cp1251.uf"
  667. };
  668. PRIVATE uint16 cp1251ToTbl[] = {
  669. #include "cp1251.ut"
  670. };
  671. PRIVATE uint16 cp1253FromTbl[] = {
  672. #include "cp1253.uf"
  673. };
  674. PRIVATE uint16 cp1253ToTbl[] = {
  675. #include "cp1253.ut"
  676. };
  677. PRIVATE uint16 cp1254FromTbl[] = {
  678. #include "cp1254.uf"
  679. };
  680. PRIVATE uint16 cp1254ToTbl[] = {
  681. #include "cp1254.ut"
  682. };
  683. PRIVATE uint16 cp1257FromTbl[] = {
  684. #include "cp1257.uf"
  685. };
  686. PRIVATE uint16 cp1257ToTbl[] = {
  687. #include "cp1257.ut"
  688. };
  689.  
  690. /*    
  691.  * Russian
  692.  */
  693. PRIVATE uint16 koi8rFromTbl[] = {
  694. #include "koi8r.uf"
  695. };
  696. PRIVATE uint16 koi8rToTbl[] = {
  697. #include "koi8r.ut"
  698. };
  699.  
  700. /*    
  701.  * OS/2 Codepages
  702.  */
  703. PRIVATE uint16 cp850FromTbl[] = {
  704. #include "cp850.uf"
  705. };
  706. PRIVATE uint16 cp850ToTbl[] = {
  707. #include "cp850.ut"
  708. };
  709. PRIVATE uint16 cp852FromTbl[] = {
  710. #include "cp852.uf"
  711. };
  712. PRIVATE uint16 cp852ToTbl[] = {
  713. #include "cp852.ut"
  714. };
  715. PRIVATE uint16 cp855FromTbl[] = {
  716. #include "cp855.uf"
  717. };
  718. PRIVATE uint16 cp855ToTbl[] = {
  719. #include "cp855.ut"
  720. };
  721. PRIVATE uint16 cp857FromTbl[] = {
  722. #include "cp857.uf"
  723. };
  724. PRIVATE uint16 cp857ToTbl[] = {
  725. #include "cp857.ut"
  726. };
  727. PRIVATE uint16 cp862FromTbl[] = {
  728. #include "cp862.uf"
  729. };
  730. PRIVATE uint16 cp862ToTbl[] = {
  731. #include "cp862.ut"
  732. };
  733. PRIVATE uint16 cp864FromTbl[] = {
  734. #include "cp864.uf"
  735. };
  736. PRIVATE uint16 cp864ToTbl[] = {
  737. #include "cp864.ut"
  738. };
  739. PRIVATE uint16 cp866FromTbl[] = {
  740. #include "cp866.uf"
  741. };
  742. PRIVATE uint16 cp866ToTbl[] = {
  743. #include "cp866.ut"
  744. };
  745. PRIVATE uint16 cp874FromTbl[] = {
  746. #include "cp874.uf"
  747. };
  748. PRIVATE uint16 cp874ToTbl[] = {
  749. #include "cp874.ut"
  750. };
  751.  
  752. /*    
  753.  * Korea
  754.  */
  755. PRIVATE uint16 koreaFromTbl[] = {
  756. #include "ksc5601.uf"
  757. };
  758. PRIVATE uint16 koreaToTbl[] = {
  759. #include "ksc5601.ut"
  760. };
  761.  
  762.  
  763. /*    
  764.  * Symbol 
  765.  */
  766. PRIVATE uint16 symbolFromTbl[] = {
  767. #include "macsymbo.uf"
  768. };
  769. PRIVATE uint16 symbolToTbl[] = {
  770. #include "macsymbo.ut"
  771. };
  772.  
  773. /*    
  774.  * Mac roman
  775.  */
  776. PRIVATE uint16 macromanFromTbl[] = {
  777. #include "macroman.uf"
  778. };
  779. PRIVATE uint16 macromanToTbl[] = {
  780. #include "macroman.ut"
  781. };
  782.  
  783. /*    
  784.  * Dingbats Stuff 
  785.  */
  786. PRIVATE uint16 dingbatFromTbl[] = {
  787. #include "macdingb.uf"
  788. };
  789. PRIVATE uint16 dingbatToTbl[] = {
  790. #include "macdingb.ut"
  791. };
  792.  
  793. /*
  794.  * Return the address of the To table given the codeset
  795.  */
  796. PRIVATE uTable* LoadToUCS2Table(uint16 csid) {
  797.     switch(csid) {
  798.     case CS_ASCII:
  799.     case CS_LATIN1:        return (uTable*) cp1252ToTbl;
  800.      case CS_UTF8:
  801.     case CS_UTF7:
  802.     case CS_UCS2:       return (uTable*) Ucs2Tbl;
  803.     case CS_LATIN2:        return (uTable*) iso8859_2ToTbl;
  804.     case CS_SJIS:        return (uTable*) japanToTbl;
  805.     case CS_BIG5:        return (uTable*) taiwanToTbl;
  806.     case CS_GB_8BIT:    return (uTable*) chinaToTbl;
  807.     case CS_8859_3:        return (uTable*) iso8859_3ToTbl;
  808.     case CS_8859_4:        return (uTable*) iso8859_4ToTbl;
  809.     case CS_8859_5:        return (uTable*) iso8859_5ToTbl;
  810.     case CS_8859_6:        return (uTable*) iso8859_6ToTbl;
  811.     case CS_8859_7:        return (uTable*) iso8859_7ToTbl;
  812.     case CS_8859_8:        return (uTable*) iso8859_8ToTbl;
  813.     case CS_8859_9:        return (uTable*) iso8859_9ToTbl;
  814.     case CS_CP_1250:    return (uTable*) cp1250ToTbl;
  815.     case CS_CP_1251:    return (uTable*) cp1251ToTbl;
  816.     case CS_CP_1253:    return (uTable*) cp1253ToTbl;
  817.     case CS_CP_1254:    return (uTable*) cp1254ToTbl;
  818.     case CS_CP_1257:    return (uTable*) cp1257ToTbl;
  819.     case CS_CP_850:        return (uTable*) cp850ToTbl;
  820.     case CS_CP_852:        return (uTable*) cp852ToTbl;
  821.     case CS_CP_855:        return (uTable*) cp855ToTbl;
  822.     case CS_CP_857:        return (uTable*) cp857ToTbl;
  823.     case CS_CP_862:        return (uTable*) cp862ToTbl;
  824.     case CS_CP_864:        return (uTable*) cp864ToTbl;
  825.     case CS_CP_866:        return (uTable*) cp866ToTbl;
  826.     case CS_CP_874:        return (uTable*) cp874ToTbl;
  827.     case CS_KOI8_R:        return (uTable*) koi8rToTbl;
  828.     case CS_KSC_8BIT:    return (uTable*) koreaToTbl;
  829.     case CS_MAC_ROMAN:    return (uTable*) macromanToTbl;
  830.     case CS_SYMBOL:        return (uTable*) symbolToTbl;
  831.     case CS_DINGBATS:    return (uTable*) dingbatToTbl;
  832.     }
  833.     return (uTable*) cp1252ToTbl;   /* This should not happen */
  834. }
  835.  
  836. /*
  837.  * Return the address of the From table given the codeset
  838.  */
  839. PRIVATE uTable* LoadFromUCS2Table(uint16 csid) {
  840.     switch(csid) {
  841.     case CS_ASCII:
  842.     case CS_LATIN1:        return (uTable*) cp1252FromTbl;
  843.      case CS_UTF8:
  844.     case CS_UTF7:
  845.     case CS_UCS2:       return (uTable*) Ucs2Tbl;
  846.     case CS_LATIN2:        return (uTable*) iso8859_2FromTbl;
  847.     case CS_SJIS:        return (uTable*) japanFromTbl;
  848.     case CS_BIG5:        return (uTable*) taiwanFromTbl;
  849.     case CS_GB_8BIT:    return (uTable*) chinaFromTbl;
  850.     case CS_8859_3:        return (uTable*) iso8859_3FromTbl;
  851.     case CS_8859_4:        return (uTable*) iso8859_4FromTbl;
  852.     case CS_8859_5:        return (uTable*) iso8859_5FromTbl;
  853.     case CS_8859_6:        return (uTable*) iso8859_6FromTbl;
  854.     case CS_8859_7:        return (uTable*) iso8859_7FromTbl;
  855.     case CS_8859_8:        return (uTable*) iso8859_8FromTbl;
  856.     case CS_8859_9:        return (uTable*) iso8859_9FromTbl;
  857.     case CS_CP_1250:    return (uTable*) cp1250FromTbl;
  858.     case CS_CP_1251:    return (uTable*) cp1251FromTbl;
  859.     case CS_CP_1253:    return (uTable*) cp1253FromTbl;
  860.     case CS_CP_1254:    return (uTable*) cp1254FromTbl;
  861.     case CS_CP_1257:    return (uTable*) cp1257FromTbl;
  862.     case CS_CP_850:        return (uTable*) cp850FromTbl;
  863.     case CS_CP_852:        return (uTable*) cp852FromTbl;
  864.     case CS_CP_855:        return (uTable*) cp855FromTbl;
  865.     case CS_CP_857:        return (uTable*) cp857FromTbl;
  866.     case CS_CP_862:        return (uTable*) cp862FromTbl;
  867.     case CS_CP_864:        return (uTable*) cp864FromTbl;
  868.     case CS_CP_866:        return (uTable*) cp866FromTbl;
  869.     case CS_CP_874:        return (uTable*) cp874FromTbl;
  870.     case CS_KOI8_R:        return (uTable*) koi8rFromTbl;
  871.     case CS_KSC_8BIT:    return (uTable*) koreaFromTbl;
  872.     case CS_MAC_ROMAN:    return (uTable*) macromanFromTbl;
  873.     case CS_SYMBOL:        return (uTable*) symbolFromTbl;
  874.     case CS_DINGBATS:    return (uTable*) dingbatFromTbl;
  875.     }
  876.     return (uTable*) cp1252FromTbl;   /* This should not happen */
  877. }
  878.  
  879.  
  880. /*
  881.  * Null functions since the tables are inline
  882.  */
  883. PRIVATE void UnloadToUCS2Table(uint16 csid, uTable *utblPtr) {}
  884. PRIVATE void UnloadFromUCS2Table(uint16 csid, uTable *utblPtr) {}
  885.  
  886. #endif /* XP_OS2 */
  887.  
  888. /*--------------------------------------------------------------------------*/
  889. /*--------------------------------------------------------------------------*/
  890. PRIVATE uRowTable* AddAndInitOneRow(uint16 hb)
  891. {
  892.     /*    Allocate uRowTablePtArray[hb] and initialize it */
  893.     uint16 i;
  894.     uRowTable *row = XP_ALLOC(sizeof(uRowTable));
  895.     if(row == NULL)
  896.     {
  897.         XP_ASSERT(row != 0);
  898.         return NULL;
  899.     }
  900.     else
  901.     {
  902.         for(i = 0; i < 256 ;i++)
  903.         {
  904.             row->value[i] = NOMAPPING;
  905.             row->info[i] = 0;
  906.         }
  907.         uRowTablePtArray[hb] = row;
  908.     }
  909.     return row;
  910. }
  911. /*--------------------------------------------------------------------------*/
  912. /*--------------------------------------------------------------------------*/
  913. PRIVATE void AddAndInitAllRows(void)
  914. {
  915.     uint16 i;
  916.     for(i=0;i<256;i++)
  917.         (void)  AddAndInitOneRow(i);
  918. }
  919. /*--------------------------------------------------------------------------*/
  920. /*--------------------------------------------------------------------------*/
  921. PRIVATE XP_Bool RowUsed(uint16 rownum)
  922. {
  923.     uint16 c;
  924.     uRowTable *row = uRowTablePtArray[ rownum] ;
  925.     
  926.     for(c=0;c<256;c++)
  927.     {
  928.         if(row->value[c] != NOMAPPING)
  929.             return TRUE;
  930.     }
  931.     return FALSE;
  932. }
  933. /*--------------------------------------------------------------------------*/
  934. /*--------------------------------------------------------------------------*/
  935. PRIVATE void FreeRow(uint16 row)
  936. {
  937.     XP_FREE(uRowTablePtArray[row]);
  938.     uRowTablePtArray[row] = NULL;
  939. }
  940. /*--------------------------------------------------------------------------*/
  941. /*--------------------------------------------------------------------------*/
  942. PRIVATE void FreeUnusedRows(void)
  943. {
  944.     uint16 i;
  945.     for(i=0;i<256;i++)
  946.     {
  947.         if(! RowUsed(i))
  948.             FreeRow(i);
  949.     }
  950. }
  951. /*--------------------------------------------------------------------------*/
  952. /*--------------------------------------------------------------------------*/
  953. PRIVATE void CheckAndAddEntry(uint16 ucs2,  uint16 med, uint16 csid)
  954. {
  955.     uint16 lb = ucs2 & 0x00FF;
  956.     uRowTable *row = uRowTablePtArray[ucs2 >> 8];
  957.     if(row->value[lb] == NOMAPPING)
  958.     {
  959.         row->value[lb]= med;
  960.         row->info[lb]= (csid & 0xFF);
  961.     }
  962. }
  963. /*--------------------------------------------------------------------------*/
  964. /*--------------------------------------------------------------------------*/
  965. PRIVATE 
  966. XP_Bool     
  967. UCS2ToValueAndInfo(uint16 ucs2, uint16* med, unsigned char* info)
  968. {
  969.     uRowTable *uRowTablePtr = uRowTablePtArray[(ucs2 >> 8)];
  970.     if( uRowTablePtr == NULL)
  971.         return FALSE;
  972.     *med =     uRowTablePtr->value[(ucs2 & 0x00ff)];
  973.     if(*med == NOMAPPING)
  974.     {
  975.         return FALSE; 
  976.     }
  977.     else
  978.     {
  979.         *info = uRowTablePtr->info[(ucs2 & 0x00ff)];
  980.         return TRUE; 
  981.     }
  982. }
  983.  
  984. /*--------------------------------------------------------------------------*/
  985. /*--------------------------------------------------------------------------*/
  986.  
  987. PRIVATE void InitUCS2Table(void)
  988. {
  989.     int16 i;
  990.     for(i=0;i<256; i++)
  991.         uRowTablePtArray[i] = NULL;
  992. }
  993. /*--------------------------------------------------------------------------*/
  994. /*--------------------------------------------------------------------------*/
  995. PUBLIC XP_Bool 
  996. UCS2_To_Other(
  997.     uint16 ucs2, 
  998.     unsigned char *out, 
  999.     uint16 outbuflen, 
  1000.     uint16* outlen,
  1001.     int16 *outcsid
  1002. )
  1003. {
  1004.     uint16 med;
  1005.     unsigned char info;
  1006.     uShiftTable* shiftTable;
  1007. #ifdef XP_MAC
  1008.     if(ucs2 == 0x000a)
  1009.         ucs2 = 0x000d;
  1010. #endif
  1011.     if(UCS2ToValueAndInfo(ucs2, &med, &info))
  1012.     {
  1013.         *outcsid = intl_GetValidCSID(info);
  1014.         XP_ASSERT(*outcsid != CS_UNKNOWN);    
  1015.         shiftTable = InfoToShiftTable(info);
  1016.         XP_ASSERT(shiftTable);    
  1017.          return uGenerate(shiftTable, (int32*)0, med, out,outbuflen, outlen);
  1018.      }
  1019.     return FALSE;
  1020. }
  1021.  
  1022.  
  1023. PRIVATE int16* unicodeCSIDList = NULL;
  1024. PRIVATE unsigned char** unicodeCharsetNameList = NULL;
  1025. PRIVATE uint16 numOfUnicodeList = 0;
  1026.  
  1027. PUBLIC int16*  INTL_GetUnicodeCSIDList(int16 * outnum)
  1028. {
  1029.     *outnum  = numOfUnicodeList;
  1030.     return unicodeCSIDList;
  1031. }
  1032. PUBLIC unsigned char **INTL_GetUnicodeCharsetList(int16 * outnum)
  1033. {
  1034.     *outnum  = numOfUnicodeList;
  1035.     return unicodeCharsetNameList;
  1036. }
  1037.  
  1038. /*--------------------------------------------------------------------------*/
  1039. /*--------------------------------------------------------------------------*/
  1040. PUBLIC void    INTL_SetUnicodeCSIDList(uint16 numOfItems, int16* csidlist)
  1041. {
  1042.     int i;
  1043.     uTable* utbl;
  1044.  
  1045.     /* This function should be called once only */
  1046.     XP_ASSERT(unicodeCSIDList == NULL);    
  1047.     XP_ASSERT(unicodeCharsetNameList == NULL);    
  1048.  
  1049.     unicodeCSIDList = XP_ALLOC(sizeof(int16) * numOfItems);
  1050.     /* needs to handle no memory */
  1051.     XP_ASSERT(unicodeCSIDList != NULL);
  1052.  
  1053.     unicodeCharsetNameList = XP_ALLOC(sizeof(unsigned char*) * numOfItems);
  1054.     /* needs to handle no memory*/
  1055.     XP_ASSERT(unicodeCharsetNameList != NULL);
  1056.  
  1057.     numOfUnicodeList = numOfItems;
  1058.     InitUCS2Table();
  1059.  
  1060.     AddAndInitAllRows();
  1061.     /*    Add the first table */
  1062.     for(i = 0 ; i < numOfItems; i++)
  1063.     {
  1064.         unicodeCSIDList[i] = csidlist[i];
  1065.         unicodeCharsetNameList[i]=  INTL_CsidToCharsetNamePt(csidlist[i]);
  1066.         if(    (csidlist[i] != CS_UTF8 ) &&
  1067.             ((utbl = LoadFromUCS2Table(csidlist[i])) != NULL))
  1068.         {
  1069.             uMapIterate(utbl,CheckAndAddEntry, csidlist[i]);
  1070.             UnloadFromUCS2Table(csidlist[i],utbl);
  1071.             
  1072.         }
  1073.     }
  1074.     FreeUnusedRows();
  1075. }
  1076. /*--------------------------------------------------------------------------*/
  1077. /*--------------------------------------------------------------------------*/
  1078. typedef struct UnicodeConverterPriv UnicodeConverterPriv;
  1079.  
  1080. typedef UnicodeConverterPriv* INTL_UnicodeToStrIteratorPriv;
  1081. struct UnicodeConverterPriv
  1082. {
  1083.     INTL_Unicode        *ustr;
  1084.     uint32            ustrlen;
  1085. };
  1086.  
  1087.  
  1088. /*--------------------------------------------------------------------------*/
  1089. /*--------------------------------------------------------------------------*/
  1090. /*    Pricate Function Declartion */
  1091. PRIVATE
  1092. XP_Bool 
  1093. UnicodeToStrWithFallback_p(
  1094.     uint16 ucs2, 
  1095.     unsigned char *out, 
  1096.     uint32  outbuflen, 
  1097.     uint32* outlen,
  1098.     uint16 *outcsid
  1099. );
  1100. PRIVATE 
  1101. XP_Bool 
  1102. UnicodeToStrFirst_p(
  1103.     uint16 ucs2, 
  1104.     unsigned char *out, 
  1105.     uint32 outbuflen, 
  1106.     uint32* outlen,
  1107.     uint16 *outcsid
  1108. );
  1109. PRIVATE
  1110. XP_Bool 
  1111. UnicodeToStrNext_p(
  1112.     uint16 ucs2, 
  1113.     unsigned char *out, 
  1114.     uint32 outbuflen, 
  1115.     uint32* outlen, 
  1116.     uint16 lastcsid
  1117. );
  1118.  
  1119.  
  1120.  
  1121. /*--------------------------------------------------------------------------*/
  1122. /*--------------------------------------------------------------------------*/
  1123. /*     the return of FLASE of this funciton only mean one thing - the outbuf 
  1124.     is not enough for this conversion */
  1125. PRIVATE
  1126. XP_Bool 
  1127. UnicodeToStrWithFallback_p(
  1128.     uint16 ucs2, 
  1129.     unsigned char *out, 
  1130.     uint32 outbuflen, 
  1131.     uint32* outlen,
  1132.     uint16 *outcsid)
  1133. {
  1134.     uint16 outlen16;
  1135.     if(! UCS2_To_Other(ucs2, out, (uint16)outbuflen, &outlen16, (int16 *)outcsid))
  1136.     {
  1137.         if(outbuflen > 2)
  1138.         {
  1139. #ifdef XP_MAC
  1140.             *outcsid = CS_MAC_ROMAN;
  1141. #else
  1142.             *outcsid = CS_LATIN1;
  1143. #endif
  1144.             out[0]= '?';
  1145.             *outlen =1;
  1146.             return TRUE;
  1147.         }
  1148.         else
  1149.             return FALSE;
  1150.     }
  1151.     else
  1152.     {
  1153.         *outlen = outlen16;
  1154.     }
  1155.     return TRUE;
  1156. }
  1157.  
  1158. /*--------------------------------------------------------------------------*/
  1159. /*--------------------------------------------------------------------------*/
  1160. PRIVATE 
  1161. XP_Bool 
  1162. UnicodeToStrFirst_p(
  1163.     uint16 ucs2, 
  1164.     unsigned char *out, 
  1165.     uint32 outbuflen, 
  1166.     uint32* outlen,
  1167.     uint16 *outcsid)
  1168. {
  1169.   return  UnicodeToStrWithFallback_p(ucs2,out,outbuflen,outlen,outcsid);
  1170. }
  1171. /*--------------------------------------------------------------------------*/
  1172. /*--------------------------------------------------------------------------*/
  1173. PRIVATE
  1174. XP_Bool 
  1175. UnicodeToStrNext_p(
  1176.     uint16 ucs2, 
  1177.     unsigned char *out, 
  1178.     uint32 outbuflen, 
  1179.     uint32* outlen, 
  1180.     uint16 lastcsid)
  1181. {
  1182.     uint16 thiscsid;
  1183.     XP_Bool retval = 
  1184.         UnicodeToStrWithFallback_p(ucs2,out,outbuflen,outlen,&thiscsid);
  1185.     return (retval && (thiscsid == lastcsid));
  1186. }
  1187. /*--------------------------------------------------------------------------*/
  1188. /*--------------------------------------------------------------------------*/
  1189.  
  1190. PUBLIC INTL_UnicodeToStrIterator    
  1191. INTL_UnicodeToStrIteratorCreate(
  1192.     INTL_Unicode*             ustr,
  1193.     uint32                     ustrlen,
  1194.     INTL_Encoding_ID         *encoding,
  1195.     unsigned char*              dest, 
  1196.     uint32                     destbuflen
  1197. )
  1198. {
  1199.     UnicodeConverterPriv* priv=0;
  1200.     priv=XP_ALLOC(sizeof(UnicodeConverterPriv));
  1201.     if(priv)
  1202.     {
  1203.         priv->ustrlen = ustrlen;
  1204.         priv->ustr = ustr;
  1205.         (void)INTL_UnicodeToStrIterate((INTL_UnicodeToStrIterator)priv, 
  1206.                                     encoding, dest, destbuflen);
  1207.     }
  1208.     else
  1209.     {
  1210.         *encoding = 0;
  1211.         dest[0] = '\0';
  1212.     }
  1213.     return (INTL_UnicodeToStrIterator)priv;
  1214. }
  1215. /*--------------------------------------------------------------------------*/
  1216. /*--------------------------------------------------------------------------*/
  1217.  
  1218. PUBLIC int INTL_UnicodeToStrIterate(
  1219.     INTL_UnicodeToStrIterator         iterator,
  1220.     INTL_Encoding_ID                 *encoding,
  1221.     unsigned char*                    dest, 
  1222.     uint32                            destbuflen
  1223. )
  1224. {
  1225.         unsigned char* orig = dest;
  1226.     UnicodeConverterPriv* priv = (UnicodeConverterPriv*)iterator;
  1227.     if(destbuflen < 2)        /* we want to make sure there at least two byte in the buffer */
  1228.         return 0;            /* first one for the first char, second one for the NULL */ 
  1229.     destbuflen -= 1;        /* resever one byte for NULL terminator */
  1230.     if((priv == NULL) || ((priv->ustrlen) == 0))
  1231.     {
  1232.         *encoding = 0;
  1233.         dest[0]='\0';
  1234.         return 0;
  1235.     }
  1236.     else
  1237.     {
  1238.         uint32 len = 0;
  1239.         if(UnicodeToStrFirst_p(*(priv->ustr),  
  1240.                 dest,destbuflen,&len,encoding))
  1241.         {
  1242.             do{
  1243.                 dest += len;
  1244.                 destbuflen -= len;
  1245.                 priv->ustr += 1;
  1246.                 priv->ustrlen -= 1 ;
  1247.             } while(    (destbuflen > 0) && 
  1248.                         ((priv->ustrlen > 0)) && 
  1249.                         UnicodeToStrNext_p(*(priv->ustr), dest, destbuflen, 
  1250.                                             &len, *encoding));
  1251.         }
  1252.         dest[0] = '\0';
  1253.         return (orig != dest);
  1254.     }
  1255. }
  1256.  
  1257. /*--------------------------------------------------------------------------*/
  1258. /*--------------------------------------------------------------------------*/
  1259. PUBLIC void    
  1260. INTL_UnicodeToStrIteratorDestroy(
  1261.     INTL_UnicodeToStrIterator iterator
  1262. )
  1263. {
  1264.     UnicodeConverterPriv* priv = (UnicodeConverterPriv*)iterator;
  1265.     if(priv)
  1266.         XP_FREE(priv);
  1267. }
  1268. /*--------------------------------------------------------------------------*/
  1269. /*--------------------------------------------------------------------------*/
  1270. PUBLIC uint32 INTL_UnicodeLen(INTL_Unicode *ustr)
  1271. {
  1272.     uint32 i;
  1273.     for(i=0;*ustr++;i++)    
  1274.         ;
  1275.     return i;
  1276. }
  1277.  
  1278. /*--------------------------------------------------------------------------*/
  1279. /*--------------------------------------------------------------------------*/
  1280. PUBLIC uint32    INTL_UnicodeToStrLen(
  1281.     INTL_Encoding_ID encoding,
  1282.     INTL_Unicode*    ustr,
  1283.     uint32 ustrlen
  1284. )
  1285. {
  1286.     /* for now, put a dump algorithm to caculate the length */
  1287.     return ustrlen * ((encoding & MULTIBYTE) ?  4 : 1) + 1;
  1288. }
  1289.  
  1290. /*--------------------------------------------------------------------------*/
  1291. /*--------------------------------------------------------------------------*/
  1292. PRIVATE 
  1293. int
  1294. LoadUCS2TableSet(uint16 csid, uTableSet* tableset,int from)
  1295. {
  1296.     UnicodeTableSet* set;
  1297.     int i;
  1298.     for(i=0;i<MAXINTERCSID;i++)
  1299.     {
  1300.         tableset->range[i].intercsid=CS_DEFAULT;
  1301.         tableset->tables[i]=NULL;
  1302.         tableset->shift[i] = NULL;
  1303.         tableset->range[i].min = 0xff;
  1304.         tableset->range[i].max = 0x00;
  1305.     }
  1306.     set = GetUnicodeTableSet(csid);
  1307.     /* If the conversion is a combination of several csid conversion, We try      */
  1308.     /* to load all of them now.                                                   */
  1309.     /* Otherwise, we simply load the one for the csid                               */
  1310.     if(set == NULL)
  1311.     {
  1312.         tableset->range[0].intercsid=csid;
  1313.         if(from)
  1314.               tableset->tables[0]=LoadFromUCS2Table(csid);
  1315.         else
  1316.               tableset->tables[0]=LoadToUCS2Table(csid);
  1317.         tableset->shift[0] = GetShiftTableFromCsid(csid);
  1318.         tableset->range[0].min = 0x00;
  1319.         tableset->range[0].max = 0xff;
  1320.         return 1;
  1321.     }
  1322.     else 
  1323.     {
  1324.         for(i=0;((i<MAXINTERCSID) && (set->range[i].intercsid != CS_DEFAULT));i++)
  1325.         {
  1326.             tableset->range[i].intercsid=set->range[i].intercsid;
  1327.             tableset->range[i].min = set->range[i].min;
  1328.             tableset->range[i].max = set->range[i].max;
  1329.             if(from)
  1330.                   tableset->tables[i]=LoadFromUCS2Table(set->range[i].intercsid);
  1331.             else
  1332.                   tableset->tables[i]=LoadToUCS2Table(set->range[i].intercsid);
  1333.             tableset->shift[i] = GetShiftTableFromCsid(set->range[i].intercsid);
  1334.             XP_ASSERT(tableset->shift[i]);
  1335.             XP_ASSERT(tableset->tables[i]);
  1336.         }
  1337.         return i;
  1338.     }
  1339. }
  1340. /*--------------------------------------------------------------------------*/
  1341. /*--------------------------------------------------------------------------*/
  1342. PRIVATE 
  1343. void     
  1344. UnloadUCS2TableSet(uTableSet *tableset,int from)
  1345. {
  1346.     int i;
  1347.     if(tableset == NULL)
  1348.         return;
  1349.     for(i=0;i<MAXINTERCSID;i++)
  1350.     {
  1351.         if((tableset->range[i].intercsid != CS_DEFAULT) && (tableset->tables[i] != NULL))
  1352.         {
  1353.             if(from)
  1354.                 UnloadFromUCS2Table(tableset->range[i].intercsid, tableset->tables[i]);
  1355.             else
  1356.                 UnloadToUCS2Table(tableset->range[i].intercsid, tableset->tables[i]);
  1357.         }
  1358.         tableset->range[i].intercsid=CS_DEFAULT;
  1359.         tableset->tables[i]=NULL;
  1360.         tableset->shift[i] = NULL;
  1361.     }
  1362. }
  1363.  
  1364.  
  1365. /*--------------------------------------------------------------------------*/
  1366. /*--------------------------------------------------------------------------*/
  1367. /*
  1368.  * utf8_to_local_encoding - UTF8 to Locally Encoded segment
  1369.  *
  1370.  * Convert a utf8 string to a Locally Encoded string.
  1371.  * Convert as characters until the encoding changes or
  1372.  * input/output space runs out.
  1373.  *
  1374.  * The segment is NOT NULL TERMINATED
  1375.  *
  1376.  * inputs: utf8 string & length
  1377.  *         buffer (pre-allocated) to hold Locally Encoded string
  1378.  *         pointer to return encoding csid
  1379.  *         pointer to return strlen of Encoded string
  1380.  *
  1381.  * output: values written to Locally Encoded string buffer
  1382.  *         encoding csid set: 
  1383.  *              >0 if successful
  1384.  *              -1 if not unicode
  1385.  *              -2 if no local encoding
  1386.  *         length of utf8 string converted returned
  1387.  *         strlen of Locally Encoded string 
  1388.  *         
  1389.  */
  1390. PUBLIC int
  1391. utf8_to_local_encoding(const unsigned char *utf8p, const int utf8len,
  1392.                         unsigned char *LE_string, int LE_string_len,
  1393.                         int *LE_written_len, int16 *LE_string_csid)
  1394. {
  1395.     int parsed_len = 0;
  1396.     int written_len = 0;
  1397.     int16 i, utf8_char_len;
  1398.     uint16 ucs2_char;
  1399.     int16 seg_encoding;
  1400.     int16 out_char_len, out_char_encoding;
  1401.     unsigned char tmpbuf[10];
  1402.     XP_Bool result;
  1403.  
  1404.     /*
  1405.      * get segment encoding (encoding of first character)
  1406.      */
  1407.     utf8_char_len = utf8_to_ucs2_char(utf8p, (int16)utf8len, &ucs2_char);
  1408.     if (utf8_char_len == -1) {
  1409.         /* its not unicode/utf8 but try to convert */
  1410.         /* it anyway so the user can see something */
  1411.         seg_encoding = -1;
  1412.     }
  1413.     else if (utf8_char_len == -2) /* not enough input characters */
  1414.         return 0;
  1415.     else {
  1416.         result = UCS2_To_Other(ucs2_char, tmpbuf, (uint16)10,
  1417.                                             (uint16*)&out_char_len, (int16*)&seg_encoding);
  1418.         if (result == FALSE) /* failed to convert */
  1419.             seg_encoding = -2; /* no local encoding */
  1420.     }
  1421.  
  1422.     /*
  1423.      * loop converting the string
  1424.      */
  1425.     while (1) {
  1426.         /*
  1427.          * convert utf8 to UCS2
  1428.          */
  1429.         utf8_char_len = utf8_to_ucs2_char(utf8p+parsed_len, (int16)(utf8len-parsed_len),
  1430.                                                         &ucs2_char);
  1431.         if (utf8_char_len == -1) { /* not utf8 */
  1432.             utf8_char_len = 1;
  1433.             out_char_encoding = -1;
  1434.             tmpbuf[0] = *(utf8p+parsed_len);
  1435.             out_char_len = 1;
  1436.         }
  1437.         else if (utf8_char_len == -2) /* no input/output space */
  1438.             break;
  1439.         else {
  1440.             /*
  1441.              * convert UCS2 to local encoding
  1442.              */
  1443.             result = UCS2_To_Other(ucs2_char, tmpbuf, (uint16)10,
  1444.                                             (uint16*)&out_char_len, (int16*)&out_char_encoding);
  1445.             if (result == FALSE) { /* failed to convert */
  1446.                 out_char_encoding = -2; /* no local encoding */
  1447.                 tmpbuf[0] = '?'; /* place holder */
  1448.                 out_char_len = 1;
  1449.             }
  1450.         }
  1451.  
  1452.         /* stop if not the same encoding */
  1453.         if (out_char_encoding != seg_encoding)
  1454.             break;
  1455.  
  1456.         /* stop if out of space for output characters */
  1457.         if ((written_len+out_char_len) >= LE_string_len-1)
  1458.             break;
  1459.  
  1460.         /*
  1461.          * add this character to the segment
  1462.          */
  1463.         for (i=0; i<out_char_len; i++) {
  1464.             LE_string[written_len+i] = tmpbuf[i];
  1465.         }
  1466.         written_len += out_char_len;
  1467.         parsed_len += utf8_char_len;
  1468.     }
  1469.  
  1470.     /* return encoding */
  1471.     *LE_string_csid = seg_encoding;
  1472.     LE_string[written_len] = '\0';
  1473.     *LE_written_len = written_len;
  1474.     /* return # of utf8 bytes parsed */
  1475.     return parsed_len;
  1476. }
  1477.  
  1478.  
  1479.  
  1480.  
  1481. /*--------------------------------------------------------------------------*/
  1482. /*--------------------------------------------------------------------------*/
  1483. PUBLIC void    INTL_UnicodeToStr(
  1484.     INTL_Encoding_ID encoding,
  1485.     INTL_Unicode*    ustr,
  1486.     uint32              ustrlen,
  1487.     unsigned char*   dest,
  1488.     uint32           destbuflen
  1489. )
  1490. {
  1491. #define INVALID_ENCODING_ID    -999
  1492.  
  1493.     uint16 u;
  1494.     uint16 med;
  1495.     uint32 cur;
  1496.     static uint16            num;
  1497.     static uTableSet        tableset;
  1498.     static INTL_Encoding_ID    lastEncoding = (INTL_Encoding_ID)INVALID_ENCODING_ID;
  1499.  
  1500.     if (encoding != lastEncoding)
  1501.     {
  1502.         /* Unload all the table we need */
  1503.         if (lastEncoding != INVALID_ENCODING_ID)
  1504.             UnloadUCS2TableSet(&tableset,TRUE);
  1505.  
  1506.         /* load all the table we need */
  1507.         num = LoadUCS2TableSet(encoding, &tableset,TRUE);
  1508.  
  1509.         lastEncoding = encoding;
  1510.     }
  1511.  
  1512.     /* For every character */
  1513.     for(cur=0; cur < ustrlen ;cur++)
  1514.     {
  1515.         int i;
  1516.         u = (*ustr++);
  1517. #ifdef XP_MAC
  1518.         if(u == 0x000a)
  1519.             u = 0x000d;
  1520. #endif
  1521.     /* Loop to every table it need to convert */
  1522.         for(i=0;i<num;i++)
  1523.         {
  1524.             if((tableset.tables[i] != NULL) &&
  1525.                (uMapCode(tableset.tables[i],u, &med)))
  1526.                     break;
  1527.         }
  1528.         if(i!=num)
  1529.         {
  1530.             uint16 outlen;
  1531.             XP_Bool ret;
  1532.             /* MAP one, gen it */
  1533.             ret = uGenerate(tableset.shift[i], 
  1534.                 (int32*)0, 
  1535.                 med, 
  1536.                 dest,
  1537.                 (uint16)destbuflen, 
  1538.                 &outlen);
  1539.  
  1540.             XP_ASSERT(ret);
  1541.  
  1542.             dest+=outlen;
  1543.             destbuflen += outlen;
  1544.         }
  1545.         else
  1546.         {
  1547.             /* Ok! right before we fall back. We take care C0 area here */
  1548.             if(u <= 0x0020)
  1549.             {
  1550.                 /* cannot map one, gen the fallback */
  1551.                 *dest++ = (unsigned char)u;
  1552.                 destbuflen--;
  1553.             }
  1554.             else
  1555.             {            
  1556.                 XP_ASSERT(destbuflen > 1);
  1557.  
  1558.                 /* cannot map one, gen the fallback */
  1559.                 *dest++ = '?';
  1560.                 destbuflen--;
  1561.             }
  1562.         }
  1563.     }
  1564.     XP_ASSERT(destbuflen > 0);
  1565.     *dest = '\0';    /* NULL terminate it */
  1566. }
  1567. /*
  1568.     intl_check_unicode_question
  1569.     Used by INTL_UnicodeToEncodingStr
  1570. */
  1571. PRIVATE uint32 intl_check_unicode_question(
  1572.     INTL_Unicode*    ustr,
  1573.     uint32              ustrlen
  1574. )
  1575. {
  1576.     INTL_Unicode* p;
  1577.     uint32 count = 0;
  1578.     for(p=ustr; ustrlen > 0  ;ustrlen--, p++)
  1579.         if(*p == 0x003F)
  1580.             count++;
  1581.     return count;    
  1582. }
  1583. /*
  1584.     intl_check_unknown_unicode
  1585.     Used by INTL_UnicodeToEncodingStr
  1586. */
  1587. PRIVATE uint32 intl_check_unknown_unicode(unsigned char*   buf)
  1588. {
  1589.     unsigned char* p;
  1590.     uint32 count = 0;
  1591.     for(p=buf; *p != '\0'; p++)
  1592.         if(*p == '?')
  1593.             count++;
  1594.     return count;    
  1595. }
  1596. /*
  1597.     INTL_UnicodeToEncodingStr
  1598.     This is an Trail and Error function which may wast a lot of performance in "THE WORST CASE"
  1599.     However, it do it's best in the best case and average case.
  1600.     IMPORTANT ASSUMPTION: The unknown Unicode is fallback to '?'
  1601. */
  1602. PUBLIC INTL_Encoding_ID    INTL_UnicodeToEncodingStr(
  1603.     INTL_Unicode*    ustr,
  1604.     uint32              ustrlen,
  1605.     unsigned char*   dest,
  1606.     uint32           destbuflen
  1607. )
  1608. {
  1609.     INTL_Encoding_ID latin1_encoding, encoding, min_error_encoding, last_convert_encoding;
  1610.     uint32 min, question;
  1611.     int16 *encodingList;
  1612.     int16 itemCount;
  1613.     int16 idx;
  1614.     
  1615. #ifdef XP_MAC
  1616.     encoding = latin1_encoding = CS_MAC_ROMAN;
  1617. #else
  1618.     encoding = latin1_encoding =  CS_LATIN1;
  1619. #endif
  1620.     /* Ok, let's try them with Latin 1 first. I believe this is for most of the case */
  1621.     INTL_UnicodeToStr(encoding,ustr,ustrlen,dest,destbuflen);
  1622.     /* Try to find the '?' in the converted string */
  1623.     min = intl_check_unknown_unicode(dest);
  1624.     if(min == 0)        /* No '?' in the converted string, it could be convert to Latin 1 */
  1625.         return encoding;
  1626.     /* The origional Unicode may contaion some '?' in unicode. Let's count it */        
  1627.     question = intl_check_unicode_question(ustr,ustrlen );
  1628.     /* The number of  '?' in the converted string match the number in unicode */
  1629.     if(min == question)    
  1630.         return encoding;
  1631.     
  1632.     last_convert_encoding = min_error_encoding = encoding;
  1633.         
  1634.     encodingList = INTL_GetUnicodeCSIDList(&itemCount);
  1635.     for(idx = 0; idx < itemCount ; idx++)
  1636.     {
  1637.         encoding = encodingList[idx];
  1638.         /* Let's ignore the following three csid
  1639.             the latin1 (we already try it 
  1640.             Symbol an Dingbat
  1641.         */
  1642.         if((encoding != latin1_encoding) && 
  1643.            (encoding != CS_SYMBOL) &&
  1644.            (encoding != CS_DINGBATS))
  1645.         {   
  1646.             uint32 unknowInThis;
  1647.             last_convert_encoding = encoding;
  1648.             INTL_UnicodeToStr(encoding,ustr,ustrlen,dest,destbuflen);
  1649.             unknowInThis = intl_check_unknown_unicode(dest);
  1650.             /* The number of  '?' in the converted string match the number in unicode */
  1651.             if(unknowInThis == question)    /* what a perfect candidcate */
  1652.                 return encoding;
  1653.             /* The number of  '?' is less then the previous smallest */
  1654.             if(unknowInThis < min)
  1655.             {   /* let's remember the encoding and the number of '?' */
  1656.                 min = unknowInThis;
  1657.                 min_error_encoding = encoding;
  1658.             }
  1659.         }
  1660.     }
  1661.     /* The min_error_encoding is not the last one we try to convert to. 
  1662.         We need to convert it again */
  1663.     if(min_error_encoding != last_convert_encoding)
  1664.         INTL_UnicodeToStr(min_error_encoding,ustr,ustrlen,dest,destbuflen);
  1665.     return min_error_encoding;
  1666. }
  1667.  
  1668. /*--------------------------------------------------------------------------*/
  1669. /*--------------------------------------------------------------------------*/
  1670. PUBLIC uint32    INTL_StrToUnicodeLen(
  1671.     INTL_Encoding_ID encoding,
  1672.     unsigned char*    src
  1673. )
  1674. {
  1675.     /* for now, put a dump algorithm to caculate the length */
  1676.     return INTL_TextToUnicodeLen(encoding, src, XP_STRLEN((char*)src));
  1677. }
  1678. /*--------------------------------------------------------------------------*/
  1679. /*--------------------------------------------------------------------------*/
  1680. PUBLIC uint32    INTL_StrToUnicode(
  1681.     INTL_Encoding_ID encoding,
  1682.     unsigned char*   src,
  1683.     INTL_Unicode*    ustr,
  1684.     uint32           ubuflen
  1685. )
  1686. {
  1687.     uint32  len = XP_STRLEN((char*)src);
  1688.     return INTL_TextToUnicode(encoding,src,len,ustr,ubuflen);
  1689. }
  1690. PUBLIC uint32    INTL_TextToUnicodeLen(
  1691.     INTL_Encoding_ID encoding,
  1692.     unsigned char*   src,
  1693.     uint32             srclen
  1694. )
  1695. {
  1696.     /* for now, put a dump algorithm to caculate the length */
  1697.     return srclen + 1;
  1698. }
  1699. PUBLIC uint32    INTL_TextToUnicode(
  1700.     INTL_Encoding_ID encoding,
  1701.     unsigned char*   src,
  1702.     uint32             srclen,
  1703.     INTL_Unicode*    ustr,
  1704.     uint32           ubuflen
  1705. )
  1706. {
  1707.     /*
  1708.       * Use the Netscape conversion tables
  1709.      */
  1710.     uint32    validlen;
  1711.     uint16 num,scanlen, med;
  1712.     uTableSet tableset;
  1713.     num = LoadUCS2TableSet(encoding, &tableset,FALSE);
  1714.     for(validlen=0;    ((srclen > 0) && ((*src) != '\0') && (ubuflen > 1));
  1715.         srclen -= scanlen, src += scanlen, ustr++, ubuflen--,validlen++)
  1716.     {
  1717.         uint16 i;
  1718.         if(*src < 0x20)
  1719.         {
  1720.             *ustr = (INTL_Unicode)(*src);
  1721.             scanlen = 1;
  1722.             continue;
  1723.         }
  1724.         for(i=0;i<num;i++)
  1725.         {
  1726.             if((tableset.tables[i] != NULL) &&
  1727.                (tableset.range[i].min <= src[0]) &&    
  1728.                (src[0] <= tableset.range[i].max) &&    
  1729.                (uScan(tableset.shift[i],(int32*) 0,src,&med,(uint16)srclen,&scanlen)))
  1730.             {
  1731.                 uMapCode(tableset.tables[i],med, ustr);
  1732.                 if(*ustr != NOMAPPING)
  1733.                     break;
  1734.             }
  1735.         }
  1736.         if(i==num)
  1737.         {
  1738. #ifdef STRICTUNICODETEST
  1739.             XP_ASSERT(i!=num);
  1740. #endif
  1741.             *ustr= NOMAPPING;
  1742.             scanlen=1;
  1743.         }
  1744.     }
  1745.     *ustr = (INTL_Unicode) 0;
  1746.     /* Unload all the table we need */
  1747.     UnloadUCS2TableSet(&tableset,FALSE);
  1748.     return validlen;
  1749. }
  1750.