Unicode.cpp
上传用户:hmc_gdtv
上传日期:2013-08-04
资源大小:798k
文件大小:37k
源码类别:

Windows Mobile

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 2001,2002,2003 Mike Matsnev.  All Rights Reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  *
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice immediately at the beginning of the file, without modification,
  10.  *    this list of conditions, and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. Absolutely no warranty of function or purpose is made by the author
  15.  *    Mike Matsnev.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  * 
  28.  * $Id: Unicode.cpp,v 1.13.2.5 2003/12/17 12:19:58 mike Exp $
  29.  * 
  30.  */
  31. #include <afx.h>
  32. #include "ptr.h"
  33. #include "Unicode.h"
  34. #ifndef CP_UTF8
  35. #define CP_UTF8 65001
  36. #endif
  37. #ifndef CP_1252
  38. #define CP_1252 1252
  39. #endif
  40. // string compare
  41. #define CmpI(s1,s2) 
  42.     (::CompareString(LOCALE_USER_DEFAULT,NORM_IGNORECASE, 
  43.     (s1),-1,(s2),-1)-2)
  44. struct CodePage {
  45.   const TCHAR *name;
  46.   const TCHAR *alias1,*alias2;
  47.   UINT codepage;
  48.   int (*length)(struct CodePage *cp,const char *mbs,int mblen);
  49.   void (*convert)(struct CodePage *cp,const char *mbs,int mblen,
  50.       wchar_t *wcs,int wclen);
  51.   const wchar_t *table;
  52. };
  53. static int    CE_cp_length(struct CodePage *cp,const char *mbs,int mblen) {
  54.   return MultiByteToWideChar(cp->codepage,0,mbs,mblen,0,NULL);
  55. }
  56. static void   CE_cp_convert(struct CodePage *cp,const char *mbs,int mblen,
  57.     wchar_t *wcs,int wclen)
  58. {
  59.   MultiByteToWideChar(cp->codepage,0,mbs,mblen,wcs,wclen);
  60. }
  61. static int    TB_cp_length(struct CodePage *cp,const char *mbs,int mblen) {
  62.   return mblen;
  63. }
  64. static void   TB_cp_convert(struct CodePage *cp,const char *mbs,int mblen,
  65.     wchar_t *wcs,int wclen)
  66. {
  67.   const char  *mbe=mbs+min(mblen,wclen);
  68.   while (mbs<mbe)
  69.     *wcs++=cp->table[(unsigned char)*mbs++];
  70. }
  71. static int    WS_cp_length(struct CodePage *cp,const char *mbs,int mblen) {
  72.   return mblen;
  73. }
  74. static void   WS_cp_convert(struct CodePage *cp,const char *mbs,int mblen,
  75.     wchar_t *wcs,int wclen)
  76. {
  77.   const char  *mbe=mbs+min(mblen,wclen);
  78.   while (mbs<mbe)
  79.     *wcs++=(unsigned char)*mbs++;
  80. }
  81. static int    UTF_cp_length(struct CodePage *cp,const char *mbs,int mblen) {
  82.   const unsigned char *mb=(const unsigned char *)mbs;
  83.   int       len=0;
  84.   while (mblen>0) {
  85.     unsigned char c=*mb++;
  86.     --mblen;
  87.     if (c<0x80) { // ascii
  88.       ++len;
  89.     } else if (c<0xe0) { // 2-byte seq
  90.       if (mblen==0) // invalid
  91. break;
  92.       if ((mb[0]&0x80)==0x80) {
  93. ++len;
  94. ++mb;
  95. --mblen;
  96.       }
  97.     } else if (*mb<0xf0) {
  98.       if (mblen<=1) // invalid
  99. break;
  100.       if ((mb[0]&0xc0)==0x80 && (mb[1]&0xc0)==0x80) {
  101. ++len;
  102. mb+=2;
  103. mblen-=2;
  104.       }
  105.     } else if (*mb<0xf4) {
  106.       if (mblen<=2) // invalid
  107. break;
  108.       if ((mb[0]&0xc0)==0x80 && (mb[1]&0xc0)==0x80 && (mb[2]&0xc0)==0x80) {
  109. ++len;
  110. mb+=3;
  111. mblen-=3;
  112.       }
  113.     } else if (*mb==0xf4) {
  114.       if (mblen<=2) // invalid
  115. break;
  116.       if ((mb[0]&0xf0)==0x80 && (mb[1]&0xc0)==0x80 && (mb[2]&0xc0)==0x80) {
  117. ++len;
  118. mb+=3;
  119. mblen-=3;
  120.       }
  121.     }
  122.   }
  123.   return len;
  124. }
  125. static void   UTF_cp_convert(struct CodePage *cp,const char *mbs,int mblen,
  126.     wchar_t *wcs,int wclen)
  127. {
  128.   const unsigned char *mb=(const unsigned char *)mbs;
  129.   int       len=0;
  130.   wchar_t       *wce=wcs+wclen;
  131.   while (mblen>0 && wcs<wce) {
  132.     unsigned char c=*mb++;
  133.     --mblen;
  134.     if (c<0x80) { // ascii
  135.       *wcs++=c;
  136.     } else if (c<0xe0) { // 2-byte seq
  137.       if (mblen==0) // invalid
  138. break;
  139.       if ((mb[0]&0x80)==0x80) {
  140. *wcs++=((wchar_t)(c&0x1f)<<6)|(*mb&0x3f);
  141. ++mb;
  142. --mblen;
  143.       }
  144.     } else if (*mb<0xf0) {
  145.       if (mblen<=1) // invalid
  146. break;
  147.       if ((mb[0]&0xc0)==0x80 && (mb[1]&0xc0)==0x80) {
  148. *wcs++=((wchar_t)(c&0x0f)<<12)|((wchar_t)(mb[0]&0x3f)<<6)|(mb[1]&0x3f);
  149. mb+=2;
  150. mblen-=2;
  151.       }
  152.     } else if (*mb<0xf4) {
  153.       if (mblen<=2) // invalid
  154. break;
  155.       if ((mb[0]&0xc0)==0x80 && (mb[1]&0xc0)==0x80 && (mb[2]&0xc0)==0x80) {
  156. *wcs++=((wchar_t)(c&0x7)<<18)|((wchar_t)(mb[0]&0x3f)<<12)|
  157. ((wchar_t)(mb[1]&0x3f)<<6)|(mb[2]&0x3f);
  158. mb+=3;
  159. mblen-=3;
  160.       }
  161.     } else if (*mb==0xf4) {
  162.       if (mblen<=2) // invalid
  163. break;
  164.       if ((mb[0]&0xf0)==0x80 && (mb[1]&0xc0)==0x80 && (mb[2]&0xc0)==0x80) {
  165. *wcs++=((wchar_t)(c&0x7)<<18)|((wchar_t)(mb[0]&0x3f)<<12)|
  166. ((wchar_t)(mb[1]&0x3f)<<6)|(mb[2]&0x3f);
  167. mb+=3;
  168. mblen-=3;
  169.       }
  170.     }
  171.   }
  172. }
  173. static struct CodePage   *codepages;
  174. static int   curcp,maxcp;
  175. static int   default_cp;
  176. static int    add_codepage(const TCHAR *name,UINT cp,const TCHAR *alias1=NULL,
  177.    const TCHAR *alias2=NULL)
  178. {
  179.   if (curcp>=maxcp) {
  180.     maxcp+=16;
  181.     codepages=(struct CodePage *)realloc(codepages,maxcp*sizeof(struct CodePage));
  182.     if (codepages==NULL)
  183.       ExitThread(0);
  184.   }
  185.   codepages[curcp].name=name;
  186.   codepages[curcp].alias1=alias1;
  187.   codepages[curcp].alias2=alias2;
  188.   codepages[curcp].codepage=cp;
  189.   codepages[curcp].length=CE_cp_length;
  190.   codepages[curcp].convert=CE_cp_convert;
  191.   codepages[curcp].table=NULL;
  192.   return curcp++;
  193. }
  194. struct {
  195.   UINT       cp;
  196.   const TCHAR *name;
  197.   const TCHAR *alias1,*alias2;
  198. } ms_codepages[]={
  199.   { 37, _T("IBM EBCDIC - U.S./Canada"), _T("IBM037"), _T("cp037") },
  200.   { 437, _T("OEM - United States"), _T("IBM437"), _T("cp437") },
  201.   { 500, _T("IBM EBCDIC - International"), _T("IBM500"), _T("cp500") },
  202.   { 737, _T("OEM - Greek 437G") },
  203.   { 775, _T("OEM - Baltic"), _T("IBM775"), _T("cp775") },
  204.   { 850, _T("OEM - Multilingual Latin I"), _T("IBM850"), _T("cp850") },
  205.   { 852, _T("OEM - Latin II"), _T("IBM852"), _T("cp852") },
  206.   { 855, _T("OEM - Cyrillic"), _T("IBM855"), _T("cp855") },
  207.   { 857, _T("OEM - Turkish"), _T("IBM857"), _T("cp857") },
  208.   { 860, _T("OEM - Portuguese"), _T("IBM860"), _T("cp860") },
  209.   { 861, _T("OEM - Icelandic"), _T("IBM861"), _T("cp861") },
  210.   { 863, _T("OEM - Canadian French"), _T("IBM863"), _T("cp863") },
  211.   { 865, _T("OEM - Nordic"), _T("IBM865"), _T("cp865") },
  212.   { 866, _T("OEM - Russian"), _T("IBM866"), _T("cp866") },
  213.   { 869, _T("OEM - Modern Greek"), _T("IBM869"), _T("cp869") },
  214.   { 874, _T("ANSI/OEM - Thai") },
  215.   { 875, _T("IBM EBCDIC - Modern Greek") },
  216.   { 932, _T("ANSI/OEM - Japanese Shift-JIS"), _T("Shift_JIS") },
  217.   { 936, _T("ANSI/OEM - Simplified Chinese GBK"), _T("GBK") },
  218.   { 949, _T("ANSI/OEM - Korean") },
  219.   { 950, _T("ANSI/OEM - Traditional Chinese Big5"), _T("Big5") },
  220.   { 1026, _T("IBM EBCDIC - Turkish (Latin-5)"), _T("cp1026") },
  221.   { 1250, _T("ANSI - Central Europe"), _T("windows-1250") },
  222.   { 1251, _T("ANSI - Cyrillic"), _T("windows-1251") },
  223.   { 1252, _T("ANSI - Latin I"), _T("windows-1252"), _T("ISO-8859-1") }, // XXX
  224.   { 1253, _T("ANSI - Greek"), _T("windows-1253") },
  225.   { 1254, _T("ANSI - Turkish"), _T("windows-1254") },
  226.   { 1255, _T("ANSI - Hebrew"), _T("windows-1255") },
  227.   { 1256, _T("ANSI - Arabic"), _T("windows-1256") },
  228.   { 1257, _T("ANSI - Baltic"), _T("windows-1257") },
  229.   { 1258, _T("ANSI/OEM - Viet Nam"), _T("windows-1258") },
  230.   { 10000, _T("MAC - Roman") },
  231.   { 10006, _T("MAC - Greek I") },
  232.   { 10007, _T("MAC - Cyrillic") },
  233.   { 10010, _T("MAC - Romania") },
  234.   { 10017, _T("MAC - Ukraine") },
  235.   { 10029, _T("MAC - Latin II") },
  236.   { 10079, _T("MAC - Icelandic") },
  237.   { 10081, _T("MAC - Turkish") },
  238.   { 10082, _T("MAC - Croatia") },
  239.   { 20127, _T("US-ASCII") },
  240.   { 20261, _T("T.61") },
  241.   { 20866, _T("Russian - KOI8"), _T("koi8-r") },
  242.   { 21866, _T("Ukrainian - KOI8-U"), _T("koi8-u") },
  243.   { 28591, _T("ISO 8859-1 Latin I"), _T("ISO-8859-1") },
  244.   { 28592, _T("ISO 8859-2 Central Europe"), _T("ISO-8859-2") },
  245.   { 28594, _T("ISO 8859-4 Baltic"), _T("ISO-8859-4") },
  246.   { 28595, _T("ISO 8859-5 Cyrillic"), _T("ISO-8859-5") },
  247.   { 28597, _T("ISO 8859-7 Greek"), _T("ISO-8859-7") },
  248.   { 28599, _T("ISO 8859-9 Latin 5"), _T("ISO-8859-9") },
  249.   { 28605, _T("ISO 8859-15 Latin 9"), _T("ISO-8859-15") },
  250.   { 65000, _T("UTF-7") },
  251.   { 65001, _T("UTF-8") },
  252. };
  253. #define NUM_MSCP    (sizeof(ms_codepages)/sizeof(ms_codepages[0]))
  254. static int  get_mscp_num(UINT cp) {
  255.   int   i=0,j=NUM_MSCP-1;
  256.   while (i<=j) {
  257.     int   m=(i+j)>>1;
  258.     if (cp<ms_codepages[m].cp)
  259.       j=m-1;
  260.     else if (cp>ms_codepages[m].cp)
  261.       i=m+1;
  262.     else
  263.       return m;
  264.   }
  265.   return -1;
  266. }
  267. static struct {
  268.   BYTE   distmap[256];
  269.   wchar_t unimap[256];
  270.   UINT   cp;
  271. } builtin_encodings[]={
  272. {{
  273. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  274. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  275. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  277. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  278. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  279. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  280. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  281. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  282. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  283. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  284. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  285. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
  286. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  287. 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
  288. 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
  289. 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
  290. 0x1e, 0x1f, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
  291. 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  292. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
  293. },{
  294. 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009,
  295. 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012, 0x0013,
  296. 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d,
  297. 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  298. 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031,
  299. 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b,
  300. 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045,
  301. 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  302. 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
  303. 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, 0x0060, 0x0061, 0x0062, 0x0063,
  304. 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d,
  305. 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  306. 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, 0x0402, 0x0403,
  307. 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039,
  308. 0x040a, 0x040c, 0x040b, 0x040f, 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022,
  309. 0x2013, 0x2014, 0x00a0, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
  310. 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9,
  311. 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, 0x00b0, 0x00b1, 0x0406, 0x0456,
  312. 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405,
  313. 0x0455, 0x0457, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
  314. 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, 0x0420, 0x0421,
  315. 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b,
  316. 0x042c, 0x042d, 0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
  317. 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
  318. 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449,
  319. 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
  320. },1251},
  321. {{
  322. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  323. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  324. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  325. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  326. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  327. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  328. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  329. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  330. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  331. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  332. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  333. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  334. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
  335. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
  336. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x01, 0x02,
  337. 0x17, 0x05, 0x06, 0x15, 0x04, 0x16, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  338. 0x10, 0x20, 0x11, 0x12, 0x13, 0x14, 0x07, 0x03, 0x1d, 0x1c, 0x08, 0x19, 0x1e,
  339. 0x1a, 0x18, 0x1b, 0x1f, 0x01, 0x02, 0x17, 0x05, 0x06, 0x15, 0x04, 0x16, 0x09,
  340. 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x20, 0x11, 0x12, 0x13, 0x14, 0x07,
  341. 0x03, 0x1d, 0x1c, 0x08, 0x19, 0x1e, 0x1a, 0x18, 0x1b,
  342. },{
  343. 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  344. 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  345. 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  346. 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  347. 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  348. 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  349. 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  350. 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  351. 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  352. 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  353. 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  354. 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  355. 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  356. 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  357. 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  358. 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
  359. 0x2500, 0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524,
  360. 0x252c, 0x2534, 0x253c, 0x2580, 0x2584, 0x2588, 0x258c, 0x2590,
  361. 0x2591, 0x2592, 0x2593, 0x2320, 0x25a0, 0x2219, 0x221a, 0x2248,
  362. 0x2264, 0x2265, 0x00a0, 0x2321, 0x00b0, 0x00b2, 0x00b7, 0x00f7,
  363. 0x2550, 0x2551, 0x2552, 0x0451, 0x2553, 0x2554, 0x2555, 0x2556,
  364. 0x2557, 0x2558, 0x2559, 0x255a, 0x255b, 0x255c, 0x255d, 0x255e,
  365. 0x255f, 0x2560, 0x2561, 0x0401, 0x2562, 0x2563, 0x2564, 0x2565,
  366. 0x2566, 0x2567, 0x2568, 0x2569, 0x256a, 0x256b, 0x256c, 0x00a9,
  367. 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
  368. 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
  369. 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
  370. 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
  371. 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
  372. 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
  373. 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
  374. 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a,
  375. }, 20866},
  376. {{
  377. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  378. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  379. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  380. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  381. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  382. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  383. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  384. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  385. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  386. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
  387. 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  388. 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
  389. 0x1d, 0x1e, 0x1f, 0x20, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
  390. 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  391. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  392. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  393. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  394. 0x00, 0x00, 0x00, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
  395. 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
  396. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  397. },{
  398. 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  399. 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  400. 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  401. 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  402. 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  403. 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  404. 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  405. 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  406. 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  407. 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  408. 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  409. 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  410. 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  411. 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  412. 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  413. 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
  414. 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
  415. 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
  416. 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
  417. 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
  418. 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
  419. 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
  420. 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
  421. 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
  422. 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
  423. 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
  424. 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
  425. 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
  426. 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
  427. 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
  428. 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040e, 0x045e,
  429. 0x00b0, 0x2219, 0x00b7, 0x221a, 0x2116, 0x00a4, 0x25a0, 0x00a0,
  430. }, 866},
  431. {{
  432.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  433.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  434.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  435.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  436.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  437.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  438.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  439.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  440.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  441.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  442.     0,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  443.     1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
  444.    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
  445.     1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
  446.    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
  447.     0,  6,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  448. },{
  449.   0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
  450.   0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
  451.   0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
  452.   0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
  453.   0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
  454.   0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
  455.   0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
  456.   0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
  457.   0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
  458.   0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
  459.   0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
  460.   0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
  461.   0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
  462.   0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
  463.   0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
  464.   0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
  465.   0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,
  466.   0x0088,0x0089,0x008a,0x008b,0x008c,0x008d,0x008e,0x008f,
  467.   0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,
  468.   0x0098,0x0099,0x009a,0x009b,0x009c,0x009d,0x009e,0x009f,
  469.   0x00a0,0x0401,0x0402,0x0403,0x0404,0x0405,0x0406,0x0407,
  470.   0x0408,0x0409,0x040a,0x040b,0x040c,0x00ad,0x040e,0x040f,
  471.   0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,
  472.   0x0418,0x0419,0x041a,0x041b,0x041c,0x041d,0x041e,0x041f,
  473.   0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,
  474.   0x0428,0x0429,0x042a,0x042b,0x042c,0x042d,0x042e,0x042f,
  475.   0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,
  476.   0x0438,0x0439,0x043a,0x043b,0x043c,0x043d,0x043e,0x043f,
  477.   0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,
  478.   0x0448,0x0449,0x044a,0x044b,0x044c,0x044d,0x044e,0x044f,
  479.   0x2116,0x0451,0x0452,0x0453,0x0454,0x0455,0x0456,0x0457,
  480.   0x0458,0x0459,0x045a,0x045b,0x045c,0x00a7,0x045e,0x045f,
  481. }, 28595},
  482. {{
  483.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  484.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  485.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  486.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  487.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  488.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  489.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  490.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  491.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  492.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  493.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  494.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  495.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  496.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  497.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  498.     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  499. },{
  500.   0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,
  501.   0x0008,0x0009,0x000a,0x000b,0x000c,0x000d,0x000e,0x000f,
  502.   0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
  503.   0x0018,0x0019,0x001a,0x001b,0x001c,0x001d,0x001e,0x001f,
  504.   0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,
  505.   0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f,
  506.   0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,
  507.   0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f,
  508.   0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,
  509.   0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f,
  510.   0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,
  511.   0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f,
  512.   0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,
  513.   0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f,
  514.   0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
  515.   0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x007f,
  516.   0x20ac,0x00a0,0x201a,0x0192,0x201e,0x2026,0x2020,0x2021,
  517.   0x02c6,0x2030,0x0160,0x2039,0x0152,0x00a0,0x017d,0x00a0,
  518.   0x00a0,0x2018,0x2019,0x201c,0x201d,0x2022,0x2013,0x2014,
  519.   0x02dc,0x2122,0x0161,0x203a,0x0153,0x00a0,0x017e,0x0178,
  520.   0x00a0,0x00a1,0x00a2,0x00a3,0x00a4,0x00a5,0x00a6,0x00a7,
  521.   0x00a8,0x00a9,0x00aa,0x00ab,0x00ac,0x00ad,0x00ae,0x00af,
  522.   0x00b0,0x00b1,0x00b2,0x00b3,0x00b4,0x00b5,0x00b6,0x00b7,
  523.   0x00b8,0x00b9,0x00ba,0x00bb,0x00bc,0x00bd,0x00be,0x00bf,
  524.   0x00c0,0x00c1,0x00c2,0x00c3,0x00c4,0x00c5,0x00c6,0x00c7,
  525.   0x00c8,0x00c9,0x00ca,0x00cb,0x00cc,0x00cd,0x00ce,0x00cf,
  526.   0x00d0,0x00d1,0x00d2,0x00d3,0x00d4,0x00d5,0x00d6,0x00d7,
  527.   0x00d8,0x00d9,0x00da,0x00db,0x00dc,0x00dd,0x00de,0x00df,
  528.   0x00e0,0x00e1,0x00e2,0x00e3,0x00e4,0x00e5,0x00e6,0x00e7,
  529.   0x00e8,0x00e9,0x00ea,0x00eb,0x00ec,0x00ed,0x00ee,0x00ef,
  530.   0x00f0,0x00f1,0x00f2,0x00f3,0x00f4,0x00f5,0x00f6,0x00f7,
  531.   0x00f8,0x00f9,0x00fa,0x00fb,0x00fc,0x00fd,0x00fe,0x00ff,
  532. },1252},
  533. };
  534. #define NUM_BUILTIN_ENCODINGS (sizeof(builtin_encodings)/sizeof(builtin_encodings[0]))
  535. #define NUMLET 33
  536. static unsigned short russian_distrib[NUMLET*NUMLET]={
  537. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  538. 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 259, 55, 298, 90, 111, 296, 12, 96, 384, 709,
  539. 284, 340, 1, 101, 381, 393, 422, 4, 1, 88, 6, 84, 49, 32, 0, 0, 0, 0, 86, 181,
  540. 0, 52, 0, 4, 0, 1, 180, 2, 0, 91, 0, 18, 86, 3, 45, 237, 0, 196, 13, 2, 73, 0,
  541. 3, 0, 0, 2, 18, 11, 271, 2, 0, 0, 36, 0, 416, 1, 7, 0, 20, 530, 0, 65, 283, 0,
  542. 12, 80, 9, 158, 548, 19, 63, 254, 15, 73, 0, 3, 2, 4, 93, 0, 0, 220, 16, 0, 0,
  543. 22, 0, 98, 0, 0, 0, 109, 30, 0, 0, 58, 0, 15, 194, 0, 59, 616, 0, 83, 0, 1, 49,
  544. 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 412, 3, 76, 1, 5, 433, 40, 0, 214, 0, 29,
  545. 63, 2, 252, 358, 9, 186, 22, 10, 132, 0, 5, 7, 4, 3, 0, 0, 60, 42, 0, 2, 21, 0,
  546. 5, 102, 200, 260, 255, 140, 83, 113, 9, 281, 170, 544, 400, 776, 18, 84, 631,
  547. 427, 403, 10, 0, 43, 31, 105, 85, 55, 0, 0, 0, 0, 11, 15, 0, 126, 0, 0, 1, 96,
  548. 347, 1, 0, 109, 0, 10, 4, 0, 126, 8, 0, 0, 0, 0, 27, 0, 0, 0, 6, 0, 0, 0, 0,
  549. 3, 0, 0, 0, 0, 488, 17, 94, 45, 109, 49, 2, 2, 37, 0, 20, 24, 40, 154, 77, 0,
  550. 34, 0, 1, 33, 0, 0, 0, 0, 0, 0, 1, 27, 12, 0, 0, 16, 0, 4, 45, 233, 40, 120,
  551. 213, 33, 191, 33, 88, 217, 485, 226, 277, 10, 16, 85, 269, 433, 0, 0, 170, 76,
  552. 96, 64, 16, 0, 0, 0, 0, 18, 124, 0, 0, 0, 0, 8, 16, 0, 0, 0, 0, 0, 3, 0, 8, 21,
  553. 2, 0, 115, 32, 34, 0, 2, 0, 15, 17, 5, 0, 0, 0, 0, 0, 0, 0, 0, 540, 0, 6, 0,
  554. 0, 43, 1, 0, 328, 0, 55, 63, 0, 42, 800, 0, 160, 40, 39, 152, 0, 0, 3, 0, 1, 0,
  555. 0, 0, 0, 0, 0, 0, 0, 849, 3, 2, 34, 52, 501, 36, 1, 629, 0, 22, 25, 0, 37,
  556. 568, 5, 0, 166, 4, 125, 0, 0, 0, 6, 0, 0, 0, 69, 373, 0, 86, 164, 0, 248, 1,
  557. 0, 8, 0, 346, 0, 0, 234, 0, 12, 28, 1, 145, 330, 4, 6, 9, 0, 144, 0, 0, 1, 7,
  558. 0, 0, 0, 105, 7, 0, 0, 45, 0, 998, 0, 0, 1, 86, 878, 2, 30, 831, 0, 34, 0, 0,
  559. 258, 1016, 0, 6, 40, 139, 350, 1, 0, 20, 14, 0, 14, 0, 374, 77, 0, 8, 109, 0,
  560. 0, 395, 640, 446, 407, 157, 241, 123, 95, 310, 212, 633, 487, 707, 25, 108,
  561. 652, 587, 575, 6, 1, 71, 9, 157, 59, 35, 0, 0, 0, 1, 12, 61, 0, 122, 0, 0, 0,
  562. 0, 226, 0, 0, 63, 0, 6, 112, 0, 26, 909, 5, 636, 0, 4, 61, 0, 0, 0, 0, 0, 0, 0,
  563. 49, 1, 0, 0, 16, 0, 880, 4, 33, 12, 82, 654, 31, 5, 417, 0, 28, 11, 18, 111,
  564. 751, 9, 18, 29, 55, 260, 21, 21, 3, 8, 17, 2, 0, 159, 45, 0, 7, 98, 0, 239, 4,
  565. 131, 14, 21, 237, 7, 1, 111, 0, 278, 256, 86, 87, 279, 205, 17, 130, 960, 65,
  566. 3, 20, 2, 29, 4, 0, 1, 29, 317, 4, 10, 392, 0, 528, 4, 203, 0, 6, 510, 0, 0,
  567. 321, 0, 63, 36, 6, 90, 1026, 15, 248, 119, 3, 97, 0, 0, 1, 5, 1, 2, 0, 173,
  568. 553, 0, 1, 70, 0, 15, 51, 81, 80, 144, 13, 102, 32, 0, 9, 65, 227, 82, 26, 0,
  569. 65, 36, 117, 146, 0, 0, 39, 0, 77, 50, 24, 0, 0, 0, 1, 105, 6, 0, 50, 0, 0, 0,
  570. 0, 20, 0, 0, 29, 0, 0, 1, 0, 0, 27, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
  571. 0, 0, 0, 0, 28, 0, 20, 0, 0, 4, 0, 0, 16, 0, 0, 11, 11, 38, 212, 0, 15, 7, 1,
  572. 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 0, 7, 0, 0, 59, 0, 0, 24, 0, 0,
  573. 0, 0, 0, 27, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 185, 0, 5,
  574. 0, 0, 226, 0, 0, 162, 0, 19, 0, 0, 94, 8, 0, 1, 0, 268, 44, 0, 0, 0, 0, 15, 0,
  575. 0, 0, 24, 0, 0, 0, 0, 66, 0, 2, 0, 0, 162, 0, 0, 155, 0, 53, 40, 0, 19, 19, 0,
  576. 1, 0, 2, 18, 0, 0, 0, 0, 0, 0, 0, 0, 58, 0, 0, 0, 0, 42, 0, 0, 0, 0, 137, 0,
  577. 0, 88, 0, 0, 0, 0, 10, 0, 0, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0,
  578. 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  579. 0, 0, 0, 0, 0, 0, 9, 0, 0, 33, 75, 14, 10, 117, 6, 9, 0, 157, 11, 167, 130, 9,
  580. 0, 12, 25, 57, 76, 0, 0, 109, 0, 16, 34, 0, 0, 0, 0, 0, 0, 1, 0, 0, 7, 0, 1,
  581. 0, 27, 0, 22, 2, 0, 82, 0, 9, 129, 0, 0, 0, 104, 3, 0, 0, 0, 15, 13, 56, 0, 0,
  582. 0, 0, 0, 42, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 2, 6, 0, 0, 0, 0, 149,
  583. 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 3, 46, 0, 26, 1, 0, 0, 0,
  584. 0, 2, 10, 0, 0, 1, 11, 43, 0, 0, 0, 0, 5, 0, 47, 0, 0, 0, 0, 2, 0, 0, 0, 0, 44,
  585. 14, 69, 10, 17, 23, 4, 19, 7, 80, 55, 57, 0, 0, 11, 63, 100, 0, 0, 21, 1, 6,
  586. 2, 39, 0, 0, 0, 0, 12, 9,
  587. };
  588. BOOL CALLBACK EnumCodePagesProc(LPTSTR name) {
  589.   UINT id;
  590.   int msnum;
  591.   if ((id=_tcstoul(name,NULL,10))!=0 && (msnum=get_mscp_num(id))>=0)
  592.     add_codepage(ms_codepages[msnum].name,id,ms_codepages[msnum].alias1,
  593. ms_codepages[msnum].alias2);
  594.   return TRUE;
  595. }
  596. static int    _cdecl enc_cmp(const void *v1,const void *v2) {
  597.   const struct CodePage *cp1=(const struct CodePage *)v1;
  598.   const struct CodePage *cp2=(const struct CodePage *)v2;
  599.   return cp1->codepage<cp2->codepage ? -1 : cp1->codepage>cp2->codepage ? 1 : 0;
  600. }
  601. static struct InitUnicode {
  602.   InitUnicode();
  603. } InitUnicode;
  604. InitUnicode::InitUnicode() {
  605.   // fetch system codepages
  606.   EnumSystemCodePages((CODEPAGE_ENUMPROC)EnumCodePagesProc,CP_INSTALLED);
  607.   qsort(codepages,curcp,sizeof(struct CodePage),enc_cmp);
  608.   // and add our own
  609.   DWORD   mask;
  610.   int   i;
  611.   for (i=mask=0;i<NUM_BUILTIN_ENCODINGS;++i) {
  612.     int icp=Unicode::GetIntCodePage(builtin_encodings[i].cp);
  613.     if (icp<0)
  614.       mask|=1<<i;
  615.     else
  616.       codepages[icp].table=builtin_encodings[i].unimap;
  617.   }
  618.   bool need_utf8=Unicode::GetIntCodePage(CP_UTF8)<0;
  619.   for (i=0;i<NUM_BUILTIN_ENCODINGS;++i)
  620.     if (mask&(1<<i)) {
  621.       int msnum=get_mscp_num(builtin_encodings[i].cp);
  622.       if (msnum>=0) {
  623. int cp=add_codepage(ms_codepages[msnum].name,ms_codepages[msnum].cp,
  624. ms_codepages[msnum].alias1,ms_codepages[msnum].alias2);
  625. codepages[cp].length=TB_cp_length;
  626. codepages[cp].convert=TB_cp_convert;
  627. codepages[cp].table=builtin_encodings[i].unimap;
  628.       }
  629.     }
  630.   if (need_utf8) {
  631.     int cp=add_codepage(_T("UTF-8"),CP_UTF8);
  632.     codepages[cp].length=UTF_cp_length;
  633.     codepages[cp].convert=UTF_cp_convert;
  634.   }
  635.   if (mask || need_utf8)
  636.     qsort(codepages,curcp,sizeof(struct CodePage),enc_cmp);
  637.   default_cp=Unicode::GetIntCodePage(1251); // XXX hardcoded
  638. }
  639. int   Unicode::WCLength(int codepage,const char *mbstr,int mblen) {
  640.   if (codepage>=0 && codepage<curcp)
  641.     return codepages[codepage].length(codepages+codepage,mbstr,mblen);
  642.   return 0;
  643. }
  644. void  Unicode::ToWC(int codepage,const char *mbstr,int mblen,
  645.     wchar_t *wcstr,int wclen)
  646. {
  647.   if (codepage>=0 && codepage<curcp)
  648.     codepages[codepage].convert(codepages+codepage,mbstr,mblen,wcstr,wclen);
  649. }
  650. int   Unicode::GetNumCodePages() {
  651.   return curcp;
  652. }
  653. const TCHAR  *Unicode::GetCodePageName(int num) {
  654.   if (num>=0 && num<curcp)
  655.     return codepages[num].name;
  656.   return NULL;
  657. }
  658. int   Unicode::GetIntCodePage(UINT mscp) {
  659.   int i=0,j=curcp;
  660.   while (i<=j) {
  661.     int   m=(i+j)>>1;
  662.     if (mscp<codepages[m].codepage)
  663.       j=m-1;
  664.     else if (mscp>codepages[m].codepage)
  665.       i=m+1;
  666.     else
  667.       return m;
  668.   }
  669.   return -1;
  670. }
  671. static UINT   detect_encoding(const unsigned char *mbs,unsigned mblen) {
  672.   unsigned i,j;
  673.   int enc=0;
  674.   int sv,msv=0;
  675.   int hist[NUMLET*NUMLET];
  676.   unsigned int prev;
  677.   unsigned char *lettermap;
  678.   if (mblen<3) /* detection needs at least a few letters :) */
  679.     return CP_1252;
  680.   if (mbs[0]=='xef' && mbs[1]=='xbb' && mbs[2]=='xbf') // utf8 bom
  681.     return CP_UTF8;
  682.   if (mblen>1024) /* don't waste too much time */
  683.     mblen=1024;
  684.   for (i=0;i<NUM_BUILTIN_ENCODINGS;++i) {
  685.     memset(hist,0,sizeof(int)*NUMLET*NUMLET);
  686.     lettermap=builtin_encodings[i].distmap;
  687.     for (j=prev=0;j<mblen;++j) {
  688.       unsigned int next=lettermap[mbs[j]];
  689.       if (next && prev)
  690.         ++hist[prev*NUMLET+next];
  691.       prev=next;
  692.     }
  693.     for (j=sv=0;j<NUMLET*NUMLET;++j)
  694.       sv+=hist[j]*russian_distrib[j];
  695.     if (sv>msv) {
  696.       enc=i;
  697.       msv=sv;
  698.     }
  699.   }
  700.   if (msv<5) /* no cyrillic letters found */
  701.     return CP_1252;
  702.   return builtin_encodings[enc].cp;
  703. }
  704. int   Unicode::DetectCodePage(const char *mbs,int mblen) {
  705.   UINT   cp=detect_encoding((const unsigned char *)mbs,mblen);
  706.   int   lcp=GetIntCodePage(cp);
  707.   return lcp<0 ? GetIntCodePage(CP_1252) : lcp; // 1252 should always be present
  708. }
  709. UINT  Unicode::GetMSCodePage(int cp) {
  710.   if (cp>=0 && cp<curcp)
  711.     return codepages[cp].codepage;
  712.   return 1251; // XXX hardcoded
  713. }
  714. int   Unicode::FindCodePage(const TCHAR *name) {
  715.   for (int i=0;i<curcp;++i)
  716.     if (!CmpI(name,codepages[i].name) ||
  717. (codepages[i].alias1 && !CmpI(name,codepages[i].alias1)) ||
  718. (codepages[i].alias2 && !CmpI(name,codepages[i].alias2)))
  719.       return i;
  720.   return -1;
  721. }
  722. int   Unicode::DefaultCodePage() {
  723.   return default_cp;
  724. }
  725. const wchar_t *Unicode::GetTable(int cp) {
  726.   if (cp>=0 && cp<curcp && codepages[cp].table)
  727.     return codepages[cp].table;
  728.   return NULL;
  729. }
  730. int Unicode::MBLength(const wchar_t *wcstr,int wclen) {
  731.   return WideCharToMultiByte(CP_ACP,0,wcstr,wclen,NULL,0,NULL,NULL);
  732. }
  733. void Unicode::ToMB(const wchar_t *wcstr,int wclen,char *mbstr,int mblen) {
  734.   WideCharToMultiByte(CP_ACP,0,wcstr,wclen,mbstr,mblen,NULL,NULL);
  735. }
  736. Buffer<wchar_t>   Unicode::ToWCbuf(int codepage,const char *mbstr,int mblen) {
  737.   int len=WCLength(codepage,mbstr,mblen);
  738.   Buffer<wchar_t> ret(len);
  739.   ToWC(codepage,mbstr,mblen,ret,len);
  740.   return ret;
  741. }
  742. Buffer<char>   Unicode::ToMBbuf(const wchar_t *wcstr,int wclen) {
  743.   int len=MBLength(wcstr,wclen);
  744.   Buffer<char> ret(len);
  745.   ToMB(wcstr,wclen,ret,len);
  746.   return ret;
  747. }
  748. CString   Unicode::ToCS(const wchar_t *wcstr,int wclen) {
  749.   return CString(wcstr,wclen);
  750. }
  751. Buffer<wchar_t>   Unicode::ToWCbuf(const CString& str) {
  752.   return Buffer<wchar_t>(str,str.GetLength());
  753. }
  754. // cstrings are implicitly nul terminated, so we can just up the size
  755. Buffer<wchar_t>   Unicode::ToWCbufZ(const CString& str) {
  756.   return Buffer<wchar_t>(str,str.GetLength()+1);
  757. }
  758. const wchar_t   *Unicode::GetCodePageNameW(int num) {
  759.   return GetCodePageName(num);
  760. }
  761. Buffer<wchar_t> Unicode::Lower(const Buffer<wchar_t>& str) {
  762.   int   rlen=LCMapString(LOCALE_USER_DEFAULT,LCMAP_LOWERCASE,str,str.size(),NULL,0);
  763.   Buffer<wchar_t>   ret(rlen);
  764.   LCMapString(LOCALE_USER_DEFAULT,LCMAP_LOWERCASE,str,str.size(),ret,ret.size());
  765.   return ret;
  766. }
  767. Buffer<char>   Unicode::SortKey(LCID lcid,const wchar_t *str,int len) {
  768.   int rlen=LCMapString(lcid,LCMAP_SORTKEY|NORM_IGNORECASE,str,len,NULL,0);
  769.   Buffer<char> ret(rlen);
  770.   LCMapString(lcid,LCMAP_SORTKEY|NORM_IGNORECASE,str,len,(wchar_t*)(char*)ret,rlen);
  771.   if (rlen>0) // don't include terminating 0
  772.     ret.setsize(rlen-1);
  773.   return ret;
  774. }
  775. Buffer<char>  Unicode::ToUtf8(const CString& cs) {
  776.   // determine length
  777.   int utflen;
  778.   const wchar_t *cp=cs;
  779.   int i;
  780.   int max=cs.GetLength();
  781.   for (i=utflen=0;i<max;++i) {
  782.     DWORD c;
  783.     if (cp[i]>=0xd800 && cp[i]<=0xdbff && i<max-1 && cp[i+1]>=0xdc00 && cp[i+1]<=0xdfff) {
  784.       c=((DWORD)(cp[i]-0xd800)<<10) + (cp[i+1]-0xdc00) + 0x10000;
  785.       ++i;
  786.     } else
  787.       c=cp[i];
  788.     if (c<128)
  789.       ++utflen;
  790.     else if (c<2048)
  791.       utflen+=2;
  792.     else if (c<65536)
  793.       utflen+=3;
  794.     else
  795.       utflen+=4;
  796.   }
  797.   Buffer<char> ret(utflen);
  798.   char *dp=ret;
  799.   for (i=0;i<max;++i) {
  800.     DWORD c;
  801.     if (cp[i]>=0xd800 && cp[i]<=0xdbff && i<max-1 && cp[i+1]>=0xdc00 && cp[i+1]<=0xdfff) {
  802.       c=((DWORD)(cp[i]-0xd800)<<10) + (cp[i+1]-0xdc00) + 0x10000;
  803.       ++i;
  804.     } else
  805.       c=cp[i];
  806.     if (c<128)
  807.       *dp++=(char)c;
  808.     else if (c<2048) {
  809.       *dp++=(char)(0xc0 | (c>>6));
  810.       *dp++=(char)(0x80 | (c&0x3f));
  811.     } else if (c<65536) {
  812.       *dp++=(char)(0xe0 | (c>>12));
  813.       *dp++=(char)(0x80 | ((c>>6)&0x3f));
  814.       *dp++=(char)(0x80 | (c&0x3f));
  815.     } else {
  816.       *dp++=(char)(0xf0 | ((c>>18) & 0x07));
  817.       *dp++=(char)(0x80 | ((c>>12) & 0x3f));
  818.       *dp++=(char)(0x80 | ((c>>6) & 0x3f));
  819.       *dp++=(char)(0x80 | (c&0x3f));
  820.     }
  821.   }
  822.   return ret;
  823. }