/* DMW_CodeConv.c Unicode --> KS code conversion API especially for shell debugging.. Copyright 2003~2009 Digital STREAM Technology, Inc. All Rights Reserved */ #include "DMW_Platform.h" #include "DMW_CodeConv.h" //#include //#include //--------------------------------------------------------- // Configurations.. #if CODE_CONV_USE_MW_TABLE #include "DMW_KsH2Uc.h" // define our own table.. // this is for the case when Application does not have conversion table #else extern UINT16 DST_cktouk[]; // if application have conversion table, // just use that symbol.. #endif //--------------------------------------------------------- #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) int DmwCodeConvPrint(char *fmt, ...) { va_list v; int n; va_start(v, fmt); n = DHL_OS_Printf(fmt, v); va_end(v); return n; } #define dprint DmwCodeConvPrint //#define dprint DHL_OS_Printf //--------------------------------------------------------- //UINT16 *dmw_ksh2uc; #define dmw_ksh2uc (DST_cktouk) // ks ÇÑ±Û ÄÚµå(0xb0a1 ~ 0xc8fe)¸¦ unicode·Î º¯È¯ÇÏ´Â Å×ÀÌºí Æ÷ÀÎÅÍ // tableÀÇ Å©±â // // 94 character per line * 25 line * 2 bytes per character = 4700 bytes // // Çѱ۸¸ º¯È¯°¡´ÉÇÔ. // UINT16 *dmw_uch2ks; // unicode ÇѱÛÄÚµå(0xac00 ~ 0xd7af)¸¦ ks ÄÚµå·Î º¯È¯ÇÏ´Â Å×À̺í.. // table Å©±â // (0xd7af - 0xac00 + 1) * 2 = 11184 * 2 = 22368 // // Unicode¿¡¼­ ´Ù·ç´Â ±ÛÀÚ°¡ ksº¸´Ù ¸¹À¸¹Ç·Î ÄÚµå¸Ê »ó¿¡ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì¿¡´Â 0ÀÌ µé¾îÀÖ´Ù. // staticÀ¸·Î Á¸ÀçÇÏ´Â tableÀÌ ¾Æ´Ï°í, ÄÚµå inverse ·çƾÀ¸·Î µ¿ÀûÀ¸·Î ¸¸µé¾îÁø´Ù. // #define IsHangulUc(c) ( ((c)>=0xac00) && ((c)<=0xd7af) ) UINT16 *DMW_GetKs2UcTable(void) { return dmw_ksh2uc; } /* for Hangul font (end) */ // ¿Ï¼ºÇü ÇÑ±Û Äڵ带 unicode·Î º¯È¯ÇÏ´Â Å×À̺í // // ÇÑ±Û '°¡'¿¡ ÇØ´çÇÏ´Â ¿Ï¼ºÇü ÄÚµå´Â 0xB0A1 ÀÌ´Ù. // UINT16 ksh_to_unicode(UINT16 ks) { // KS ÇÑ±Û Äڵ带 Unicode Çѱ۷Πº¯È¯ÇÏ´Â ÇÔ¼ö.. // KS ÄÚµåÀ̳ª ÇѱÛÀÌ ¾Æ´Ï¸é ÇöÀç 0À» ¸®ÅÏÇÑ´Ù. // // Unicode »ó¿¡¼­ 0x0000Àº NULLÀ» ÀǹÌÇÔ. // UINT8 c1, c2; int block; // big endianÀ» °¡Á¤ÇÑ °æ¿ì ÀÓ.. platform independant ±¸ÇöÀ» ¿øÇϸé UINT8 * pointer·Î ÀÔ·ÂÀ» ¹ÞÀ¸¸é µÈ´Ù. c1 = (ks >> 8); c2 = (ks & 0xff); // ks code map ¿µ¿ª¿¡ ¼ÓÇÑ ±ÛÀÚÀÎÁö üũ.. if (c1 < 0xA1 || c1 > 0xFE) { //dprint("c1 is not ks code!!\n"); return 0; } if (c2 < 0xA1 || c2 > 0xFE) { //dprint("c2 is not ks code!!\n"); return 0; } // ÇѱÛÀÎÁö °Ë»ç.. if (c1 < 0xB0 || c1 > 0xC8) { //dprint("c1 is not hangul!!\n"); //return 0; return 0x003F; // cafrii 041126 fix // ÇѱÛÀº ¾Æ´ÏÁö¸¸ KS ÄÚµå´Â ¸ÂÀ¸¹Ç·Î '?' ±ÛÀÚ¸¦ ÁÖÀÚ. } // block number (0, 1, 2, ..) °áÁ¤.. block = c1 - 0xB0; //dprint("block number %d\n", block); return dmw_ksh2uc[block*94 + (c2-0xA1)]; } int DMW_InitCodeConvLib(void) { int k; if (dmw_uch2ks) { //dprint("check code: %x %x\n", dmw_uch2ks[0], dmw_uch2ks[11184-19]); if (dmw_uch2ks[0] == 0xb0a1 && dmw_uch2ks[11184-19] == 0xc8fe) { // check whether first and last code are correct.. //dprint("already inited..\n"); return statusOK; // it seems already initialized.. } // if not, free and realloc.. DHL_OS_Free((void**)&dmw_uch2ks); } dmw_uch2ks = DHL_OS_Malloc(2 * (0xD7AF - 0xAC00 + 1)); if (dmw_uch2ks == NULL) return statusOutOfMemory; memset(dmw_uch2ks, 0, 2 * (0xD7AF - 0xAC00 + 1)); #if 1 // °¡³ª´Ù ¼ø¼­·Î Á¤·ÄµÇ¾î ÀÖÀ¸¹Ç·Î ÀÌ Æ¯¼ºÀ» Àß ÀÌ¿ëÇÏ¸é »¡¸® ÃʱâÈ­°¡ °¡´ÉÇÏ´Ù.. // // memset(dmw_uch2ks, 0, sizeof(xx)); // ÀÌ¹Ì ÃʱâÈ­ µÈ »óÅÂÀÌ´Ù.. for (k=0; k<25*94; k++) { //if (dmw_ksh2uc[k] - 0xac00 >= 11184) dprint("!! range over!!\n"); dmw_uch2ks[dmw_ksh2uc[k] - 0xac00] = ((0xB0 + k/94) << 8) + (0xA1 + k%94); } #else // brute search algorithm.. for (uc = 0xAC00; uc <= 0xD7AF; uc++) // total 11184 character.. { for (k=0; k<25*94; k++) { // search 2350 character table.. if (dmw_ksh2uc[k] == uc) { // found!!! break; } } ks = (k>=25*94) ? 0 : ((0xB0 + k/94) << 8) + (0xA1 + k%94); dmw_uch2ks[uc-0xac00] = ks; } #endif return statusOK; } //--------------------------------- // DMW_ConvKs2Uc // // KS ¹®ÀÚ¿­À» Unicode·Î º¯È¯. NULL (0x0000) À¸·Î Á¾·áµÇ¹Ç·Î // º°µµÀÇ length Á¤º¸´Â ¸®ÅÏÇÏÁö ¾Ê´Â´Ù. // ÇÊ¿äÇÑ ¸Þ¸ð¸®´Â ³»ºÎ¿¡¼­ ÇÒ´çÇØ¼­ »ç¿ëÇÑ´Ù. // »ç¿ë ÈÄ¿¡ DMW_FreeUcString À¸·Î ¸Þ¸ð¸®¸¦ ÇØÁ¦ÇØ Áà¾ß ÇÑ´Ù. // // 'len'Àº ks_charÀÇ ¹®ÀÚ¿­ ±æÀÌ (null Á¦¿Ü)À̸ç // À½ÀÇ °ªÀ» ÁöÁ¤ÇÒ °æ¿ì strlen ÇÔ¼ö·Î ÀÚµ¿ °áÁ¤µÈ´Ù. // // cafrii 041126 add UINT16 *DMW_ConvKs2Uc(char *ks_char, int len) { // ÁÖÀÇ! »ç¿ë ÈÄ¿¡ ¸®ÅϵǴ uc ¸Þ¸ð¸®¸¦ ÇØÁ¦ÇÏ¿©¾ß ÇÔ. // UINT16 *ucs; UINT16 uc; int i, k, uc_len; UINT8 *ks = (UINT8 *) ks_char; if (len < 0) len = strlen((const char *)ks); //dprint("ConvKs2Uc: ascii %d bytes (except \\0)\n", len); uc_len = 0; for (i=0; i unicode %04x", ks[i], ks[i+1], uc); // ks[i], ks[i+1] ÀÌ ÇϳªÀÇ unicode ÀÌ´Ù. ucs[k++] = uc; i++; } } else { // ¸¶Áö¸· ±ÛÀÚÀÓ.. ucs[k++] = (UINT16) ks[i]; } //dprint("\n"); } // null termination.. ucs[k] = 0; return ucs; } //--------------------------------- // DMW_ConvUc2Ks // // UINT8 *DMW_ConvUc2Ks(UINT16 *uc_16, int len) { // unicode stringÀ» Ks ÄÚµå·Î º¯È¯ÇÏ¿© ¸®ÅÏÇÑ´Ù. // º¯È¯¿¡ ÇÊ¿äÇÑ ¸Þ¸ð¸®´Â ³»ºÎÀûÀ¸·Î µ¿Àû ÇÒ´çÇÑ´Ù. // »ç¿ë ÈÄ ²À DMW_FreeKsStringÀ» ÀÌ¿ëÇÏ¿© ÇØÁ¦ÇØ¾ß ÇÑ´Ù. // // len Àº UINT16 ÇüÅÂÀÇ unicode ¹®ÀÚ °¹¼öÀÌ´Ù. (byte size°¡ ¾Æ´Ô¿¡ À¯ÀÇ!) // len ÀÌ negative°ªÀ» °¡Áö¸é Null terminated stringÀ¸·Î °£ÁÖÇÑ´Ù. // // ¸®ÅϵǴ ¹®ÀÚ¿­Àº null-terminate µÈ »óÅÂÀÌ´Ù. #define DMW_CONV_MAX_STRING_LEN 4096 // Áö¿øÇÏ´Â stringÀÇ ±æÀÌ¿¡ Á¦ÇÑÀ» µÎÀÚ.. ¹ÙÀÌÆ® ¼ö°¡ ¾Æ´Ï¶ó ±ÛÀÚ ¼öÀÌ´Ù. // Psip table º¯È¯¿¡ ÁÖ·Î »ç¿ëÇÒ °ÍÀ̹ǷΠ4K¸é ÃæºÐÇÏ´Ù. // uc pointer°¡ 16 bit alignÀÌ Àß ¾ÈµÇ¾î ÀÖÀ» ¼öµµ ÀÖÀ¸¹Ç·Î, byte´ÜÀ§·Î Àо »ç¿ëÇÏÀÚ. // // cafrii 081006, endian ¿¡ µû¶ó ´Ù¸£°Ô µ¿ÀÛÇÏÁö ¾Êµµ·Ï ±×³É 16 bit·Î ó¸®. // //#define UC(n) ((uc[2*(n)]<<8)|uc[2*(n)+1]) #define UC(n) (uc_16[n]) //UINT8 *uc = (UINT8 *)uc_16; int i, err; UINT16 ks; int offset; // byte offset of KS string buf UINT8 *buf; // ks string buf int bufsize; int dbg = 0; if (len < 0) { // length¸¦ °è»êÇÑ´Ù. for (i=0; i bufsize-1) break; buf[offset++] = (ks >> 8) & 0xff; buf[offset++] = (ks & 0xff); if (dbg) dprint("\t UC[%d] : %04x --> H: %04x (%c%c)\n", i, UC(i), ks, buf[offset-2], buf[offset-1]); } else { if (((UC(i) >> 8) & 0xff) == 0) { // seems to be english.. if (offset+1 > bufsize-1) break; buf[offset++] = (UC(i) & 0xff); if (dbg) dprint("\t UC[%d] : %04x --> E: %02x (%c)\n", i, UC(i), buf[offset-1], buf[offset-1]); } else { if (offset+5 > bufsize-1) break; sprintf((char *)&buf[offset], "#%04x", UC(i)); offset += 5; if (dbg) dprint("\t UC[%d] : %04x --> ?\n", i, UC(i)); } } } buf[offset++] = 0; // null termination.. if (dbg) dprint(" total %d bytes..\n", offset); return buf; #undef UC } void DMW_FreeKsString(UINT8 *ks) { //dprint("free buffer %08x..\n", ks); DHL_OS_Free((void**)&ks); } void DMW_FreeUcString(UINT16 *uc) { DHL_OS_Free((void**)&uc); } /* note! PSIP multiple stringÀÇ unicode´Â ¸ðµÎ big endian À¸·Î encoding µÇ¾î ÀÖÀ¸¹Ç·Î Little endian system¿¡¼­ PSIP ¹®ÀÚ¿­À» Ãâ·ÂÇÒ ¶§¿¡´Â (UINT8 *) --> (UINT16 *) ¿Í °°ÀÌ ¹Ù·Î casing ¿¬»êÀ» ÇÏ¸é ¾ÈµÈ´Ù. */ int DMW_UniPrint(UINT16 *ucs, int len) { UINT8 *s; //dprint("DMW_UniPrint (%x, %d)\n", ucs, len); s = DMW_ConvUc2Ks(ucs, len); if (s) { //dprint("buffer: %08x\n", s); dprint((char *)s); //dprint("free buffer %08x..\n", s); DMW_FreeKsString(s); } return 0; } //----------------------- // DMW_Unicode2Ks // // Unicode stringÀ» ascii stringÀ¸·Î º¯È¯ÇÏ¿© 'buf' ¿¡ ÀúÀåÇÑ´Ù. // // len Àº Unicode ¹®ÀÚ °¹¼öÀÌ´Ù. (byte char °¹¼ö°¡ ¾Æ´Ô!!) // len ÀÌ 0À̸é NULL terminated string À̶ó´Â ¶æÀÓ // char *DMW_Unicode2Ks(UINT16 *ucs, int len, char *buf) { #if 1 // cafrii 041103 add, for korean 'short name' display static char buf_0[256]; // ¹öÆÛ¸¦ ÁöÁ¤ÇÏÁö ¾Ê´Â °æ¿ì¿¡´Â ÃÖ´ë 255 ¹ÙÀÌÆ® ±îÁö¸¸ Áö¿øÇϵµ·Ï ÇÏÀÚ. char *s; int bytelen; if (buf == NULL) buf = buf_0; s = (char *)DMW_ConvUc2Ks((UINT16 *)ucs, len>0 ? len : -1); bytelen = strlen(s); // KS º¯È¯µÈ ¹®ÀÚ¿­ÀÇ ¹ÙÀÌÆ® ±æÀÌ (¹®ÀÚ °¹¼ö¶û ÀÏÄ¡ÇÏÁö ¾ÊÀ½) memcpy(buf, s, min(256, bytelen+1)); // null terminator ±îÁö º¹»ç.. DMW_FreeKsString((UINT8 *)s); return buf; #else // ±×³É ¿µ¹® ascii ¸¸ Ç¥½ÃÇÏ´Â °£´ÜÇÑ ±¸Çö.. static char buf_0[256]; int i; if (buf == NULL) buf = buf_0; if (len < 0) { for (i=0; i<255; i++) { // ÃÖ´ë ±æÀÌ´Â 256À¸·Î Á¦ÇÑ. if (ucs[i] == 0) break; } len = i; } for (i=0; i> 8) == 0) // it seems ascii buf[i] = ucs[i] & 0xff; else buf[i] = '?'; } return buf; #endif } //--------------------------- // DMW_MakeRandomKsString // // Å×½ºÆ®¸¦ À§Çؼ­ ·£´ýÇÑ ¹®ÀÚ¿­À» ¸¸µå´Â ÇÔ¼ö. // ÁöÁ¤ÇÑ ¹öÆÛ¿¡ ÀÓÀÇ ±æÀÇÀÇ ÀÓÀÇ ¹®ÀÚ¿­À» ¸¸µç´Ù. // // mode = 0 : ¿µ¹® ¹®ÀÚ¿­ // mode = 1 : ÇÑ±Û ¹®ÀÚ¿­ // mode = 2~ : ¿µ¹®/ÇÑ±Û È¥¿ë.. // char *DMW_MakeRandomKsString(char *buf, int size, int mode) { int k, bHangle = 0; char c1, c2; size--; for (k=0; k= size) // ¸¶Áö¸· ±ÛÀÚ´Â ¿µ¹®À¸·Î Á¾·áÇØ¾ß ÇÔ.. bHangle = 0; // ¿µ¹®.. else if (rand() % 3 == 0) bHangle = !bHangle; } if (bHangle == 0) { buf[k] = rand() % (0x7A - 0x2A + 1) + 0x2A; if (buf[k] == '%' || buf[k] == '\\' || buf[k] == '#') buf[k] = 'A'; } else { if (k+1 >= size) { buf[k] = '.'; break; } // ·£´ý ÇѱÛ.. c1 = rand() % (0xC8 - 0xB0 + 1) + 0xB0; c2 = rand() % (0xFE - 0xA1 + 1) + 0xA1; buf[k] = c1; k++; buf[k] = c2; } } buf[k] = 0; return buf; } //--------------------------- // DMW_MakeRandomKsString // // strlen ÀÇ unicode ¹öÀüÀÌ´Ù. // // cafrii 041126 add int DMW_UcStringLen(UINT16 *ucs) { int len = 0; if (ucs == NULL) return 0; while (ucs[len]) len++; return len; } //--------------------------- // Unicode string library.. // UniStrLen // unicode version of strcpy int UniStrLen(UINT16 *str) { register UINT16 *p = str; while (*p) p++; return (int)(p - str); } // UniStrCopy // unicode version of strcpy UINT16 *UniStrCopy(UINT16 *dst, UINT16 *src) { register UINT16 *d = dst, *s = src; while (*s) *d++ = *s++; *d = 0; return dst; } // UniStrNCopy // unicode version of strncpy UINT16 *UniStrNCopy(UINT16 *dst, UINT16 *src, int len) { register int n = 0; register UINT16 *d = dst, *s = src; while (*s && n < len) { *d++ = *s++; n++; } if (n < len) *d = 0; return dst; } // UniStrCat // unicode version of strcat UINT16 *UniStrCat(UINT16 *dst, UINT16 *src) { register UINT16 *s = src, *d = dst; // search last position while (*d) d++; // strcpy while (*s) *d++ = *s++; *d = 0; // null terminate return dst; } // UniStrCompare // unicode version of strcmp int UniStrCompare(UINT16 *string1, UINT16 *string2) { register UINT16 *str1 = string1, *str2 = string2; for (; *str1 != 0 || *str2 != 0; str1++, str2++) { if (*str1 != *str2) return (*str1 - *str2); } return 0; } // UniStrTrim // cut out trailing unnecessary space. // return string pointer UINT16 *UniStrTrim(UINT16 *uStr) { register UINT16 *s = uStr; // search tail while (*s && *s != ' ') s++; // now, *s is 0 or space. *s = 0; return uStr; } // UniStrFromAscii // just convert char string to Unicode string. // only applicable in ascii code. void UniStrFromAscii(UINT16 *ustr, char *str) { while (*str) *ustr++ = (UINT16)(*str++); *ustr = 0; } // convert one Hex character to digit #define HEX_CH_2_DIGIT(c) ( \ ((c)>='0' && (c)<='9') ? (c)-'0' : \ ((c)>='a' && (c)<='f') ? (c)-'a'+10 : \ ((c)>='A' && (c)<='F') ? (c)-'A'+10 : 0) // convert two character hax to digit static UINT16 ConvHexToInt(char ch1, char ch2) { return ((HEX_CH_2_DIGIT(ch1)<<4U) | HEX_CH_2_DIGIT(ch2)); } // UniStrCreate // convert string to unicode string // non-Latin ASCII can be converted using "&" escaper. // uStr can be null. in that case, internal static buffer is used (max 79 chars) // return converted unicode string pointer UINT16 *UniStrCreate(char *cStr, UINT16 *uStr) { static UINT16 sUStrBuf[80]; // provide temporary buffer register UINT16 *u; register char *p; p = cStr; u = uStr ? uStr : sUStrBuf; for (; *p; p++, u++) { if (*p != '&') *u = (UINT16)(*p); else { if (*(++p) == '&') *u = (UINT16)'&'; else { *u = ConvHexToInt(p[0], p[1]); p++; } } } *u = 0; // null terminate return uStr ? uStr : sUStrBuf; } #if 0 _____TEST_______() #endif // cafrii 041126 add void TestConvKs2Uc(int number) { int i; char buf[100]; UINT16 *ucs; srand(DHL_OS_GetMsCount()); if (number == 0) number = 20; for (i=0; i