/*++ Copyright (c) 1991-1999, Microsoft Corporation All rights reserved. Module Name: c_iscii.c Abstract: This file contains the main functions for this module. External Routines in this file: DllEntry NlsDllCodePageTranslation Revision History: 2-28-98 KChang Created. --*/ //////////////////////////////////////////////////////////////////////////// // // Conversions for Ten ISCII codepages // // 57002 : Devanagari // 57003 : Bengali // 57004 : Tamil // 57005 : Telugu // 57006 : Assamese (same as Bengali) // 57007 : Oriya // 57008 : Kannada // 57009 : Malayalam // 57010 : Gujarati // 57011 : Punjabi (Gurmukhi) // //////////////////////////////////////////////////////////////////////////// // // Include Files. // #include #include "c_iscii.h" // // Forward Declarations. // DWORD MBToWC( BYTE CP, LPSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar); DWORD WCToMB( BYTE CP, LPWSTR lpWideCharStr, int cchWideChar, LPSTR lpMBStr, int cchMultiByte); //-------------------------------------------------------------------------// // DLL ENTRY POINT // //-------------------------------------------------------------------------// //////////////////////////////////////////////////////////////////////////// // // DllEntry // // DLL Entry initialization procedure. // // 10-30-96 JulieB Created. //////////////////////////////////////////////////////////////////////////// BOOL DllEntry( HANDLE hModule, DWORD dwReason, LPVOID lpRes) { switch (dwReason) { case ( DLL_THREAD_ATTACH ) : { return (TRUE); } case ( DLL_THREAD_DETACH ) : { return (TRUE); } case ( DLL_PROCESS_ATTACH ) : { return (TRUE); } case ( DLL_PROCESS_DETACH ) : { return (TRUE); } } return (FALSE); hModule; lpRes; } //-------------------------------------------------------------------------// // EXTERNAL ROUTINES // //-------------------------------------------------------------------------// //////////////////////////////////////////////////////////////////////////// // // NlsDllCodePageTranslation // // This routine is the main exported procedure for the functionality in // this DLL. All calls to this DLL must go through this function. // //////////////////////////////////////////////////////////////////////////// DWORD NlsDllCodePageTranslation( DWORD CodePage, DWORD dwFlags, LPSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar, LPCPINFO lpCPInfo) { BYTE CP; if ((CodePage < 57002) || (CodePage > 57011)) { SetLastError(ERROR_INVALID_PARAMETER); return (0); } CP = (BYTE)(CodePage % 100); switch (dwFlags) { case ( NLS_CP_CPINFO ) : { memset(lpCPInfo, 0, sizeof(CPINFO)); lpCPInfo->MaxCharSize = 4; lpCPInfo->DefaultChar[0] = SUB; // // The lead-byte does not apply here, leave them all NULL. // return (TRUE); } case ( NLS_CP_MBTOWC ) : { if (cchMultiByte == -1) { cchMultiByte = strlen(lpMultiByteStr) + 1; } return (MBToWC( CP, lpMultiByteStr, cchMultiByte, lpWideCharStr, cchWideChar )); } case ( NLS_CP_WCTOMB ) : { int cchMBCount; if (cchWideChar == -1) { cchWideChar = wcslen(lpWideCharStr) + 1; } cchMBCount = WCToMB( CP, lpWideCharStr, cchWideChar, lpMultiByteStr, cchMultiByte ); return (cchMBCount); } } // // This shouldn't happen since this function gets called by // the NLS API routines. // SetLastError(ERROR_INVALID_PARAMETER); return (0); } //-------------------------------------------------------------------------// // INTERNAL ROUTINES // //-------------------------------------------------------------------------// //////////////////////////////////////////////////////////////////////////// // // MBToWC // // This routine does the translations from ISCII to Unicode. // //////////////////////////////////////////////////////////////////////////// DWORD MBToWC( BYTE CP, LPSTR lpMultiByteStr, int cchMultiByte, LPWSTR lpWideCharStr, int cchWideChar) { BYTE CurCP = CP; int ctr; int cchWCCount = 0; LPWSTR lpWCTempStr; // // Allocate a buffer of the appropriate size. // Use sizeof(WCHAR) because size could potentially double if // the buffer contains all halfwidth Katakanas // lpWCTempStr = (LPWSTR)NLS_ALLOC_MEM(cchMultiByte * sizeof(WCHAR)); if (lpWCTempStr == NULL) { SetLastError(ERROR_OUTOFMEMORY); return (0); } for (ctr = 0; ctr < cchMultiByte; ctr++) { BYTE mb = (BYTE)lpMultiByteStr[ctr]; if (mb < MB_Beg) { lpWCTempStr[cchWCCount++] = (WCHAR)mb; } else if (mb == ATR) { if (ctr >= (cchMultiByte - 1)) { // // Incomplete ATR. // lpWCTempStr[cchWCCount++] = SUB; } else { BYTE mb1 = (BYTE)lpMultiByteStr[ctr + 1]; if ((mb1 < 0x40) || (mb1 > 0x4B)) { lpWCTempStr[cchWCCount++] = SUB; } else { // // Bug #239926 10/29/00 WEIWU // We don't support Roman script transliteration yet. // To avoid invoking NULL table, we treat ATR code 0x41 as 0x40. // if (mb1 == 0x40 || mb1 == 0x41) { CurCP = CP; } else { CurCP = mb1 & 0x0F; } ctr++; } } } else { WCHAR U1 = UniChar(CurCP, mb); WCHAR U21 = TwoTo1U(CurCP, mb); if (U21 == 0) { lpWCTempStr[cchWCCount++] = U1; } else { // // Possible two MBs to one Unicode. // if (ctr >= (cchMultiByte - 1)) { lpWCTempStr[cchWCCount++] = U1; } else { BYTE mb1 = (BYTE)lpMultiByteStr[ctr + 1]; if (mb == VIRAMA) { lpWCTempStr[cchWCCount++] = U1; if (mb1 == VIRAMA) { lpWCTempStr[cchWCCount++] = ZWNJ; // ZWNJ = U+200C ctr++; } else if (mb1 == NUKTA) { lpWCTempStr[cchWCCount++] = ZWJ; // U+200D ctr++; } } else if ((U21 & 0xf000) == 0) { if (mb1 == SecondByte[1]) { // // NextByte == 0xe9 ? // lpWCTempStr[cchWCCount++] = U21; ctr++; } else { lpWCTempStr[cchWCCount++] = U1; } } else { // // Devanagari EXT // if (mb1 == ExtMBList[0].mb) // 0xf0_0xb8 { lpWCTempStr[cchWCCount++] = ExtMBList[0].wc; // U+0952 ctr++; } else if (mb1 == ExtMBList[1].mb) // 0xf0_0xbf { lpWCTempStr[cchWCCount++] = ExtMBList[1].wc; // U+0970 ctr++; } else { lpWCTempStr[cchWCCount++] = SUB; } } } } } } if (cchWideChar) { if (cchWCCount > cchWideChar) { // // Output buffer is too small. // NLS_FREE_MEM(lpWCTempStr); SetLastError(ERROR_INSUFFICIENT_BUFFER); return (0); } wcsncpy(lpWideCharStr, lpWCTempStr, cchWCCount); } NLS_FREE_MEM(lpWCTempStr); return (cchWCCount); } //////////////////////////////////////////////////////////////////////////// // // WCToMB // // This routine does the translations from Unicode to ISCII. // //////////////////////////////////////////////////////////////////////////// DWORD WCToMB( BYTE CP, LPWSTR lpWideCharStr, int cchWideChar, LPSTR lpMBStr, int cchMultiByte) { BYTE CurCP = CP; int ctr; int cchMBCount = 0; LPSTR lpMBTmpStr; lpMBTmpStr = (LPSTR)NLS_ALLOC_MEM(cchWideChar * 4); if (lpMBTmpStr == NULL) { SetLastError(ERROR_OUTOFMEMORY); return (0); } for (ctr = 0; ctr < cchWideChar; ctr++) { WCHAR wc = lpWideCharStr[ctr]; if (wc < (WCHAR)MB_Beg) { lpMBTmpStr[cchMBCount++] = (BYTE)wc; } else if ((wc < WC_Beg) || (wc > WC_End)) { lpMBTmpStr[cchMBCount++] = SUB; } else { BYTE mb = MBChar(wc); if ((Script(wc) != 0) && (Script(wc) != CurCP)) { lpMBTmpStr[cchMBCount++] = (BYTE)ATR; CurCP = Script(wc); lpMBTmpStr[cchMBCount++] = CurCP | 0x40; } lpMBTmpStr[cchMBCount++] = mb; if (mb == VIRAMA) { if (ctr < (cchMultiByte - 1)) { WCHAR wc1 = lpWideCharStr[ctr + 1]; if (wc1 == ZWNJ) { lpMBTmpStr[cchMBCount++] = VIRAMA; ctr++; } else if (wc1 == ZWJ) { lpMBTmpStr[cchMBCount++] = NUKTA; ctr++; } } } else if (OneU_2M(wc) != 0) { lpMBTmpStr[cchMBCount++] = SecondByte[OneU_2M(wc) >> 12]; } } } if (cchMultiByte) { if (cchMBCount > cchMultiByte) { // // Output buffer is too small. // NLS_FREE_MEM(lpMBTmpStr); SetLastError(ERROR_INSUFFICIENT_BUFFER); return (0); } strncpy(lpMBStr, lpMBTmpStr, cchMBCount); } NLS_FREE_MEM(lpMBTmpStr); return (cchMBCount); }