/**************************************************************************\ * chsuconv.c -- convert to/from unicode using * MulitByteToWideChar & WideCharToMulitByte * * Steve Firebaugh * Microsoft Developer Support * Copyright (C) 1992-1999 Microsoft Inc. * \**************************************************************************/ #include "chnuconv.h" #include "resource.h" /**************************************************************************\ * Global Data Items \**************************************************************************/ /* Global variables storing the source and destination "type" information. * * used to communicate between main wnd proc, and *OptionsProc. * * gTypeSource - stores the type interpretation of the source data * (and implicitly the destination data.) * TYPEUNKNOWN: indeterminant... not set. Can not do conversion. * TYPEUNICODE: source unicode & destination giDestinationCodePage. * TYPECODEPAGE: source giSourceCodePage & destination unicode. * * giSourceCodePage stores valid source code page iff gTypeSource == TRUE * giDestinationCodePage stores valid destination code page iff gTypeSource == FALSE * */ int gTypeSource; int gTypeSourceID; UINT giSourceCodePage; int gTypeDest; int gTypeDestID; UINT giDestinationCodePage; int giRBInit; TCHAR szDataOptionsDlg[40]; /* Pointers to the source and destination data, and the * count of bytes in each of the buffers. */ PBYTE pSourceData = NULL; PBYTE pDestinationData = NULL; PBYTE pTempData1 = NULL; int nBytesSource = NODATA; int nBytesDestination = NODATA; PBYTE pTempData = NULL; PBYTE pViewSourceData = NULL; int nBytesTemp = NODATA; BOOL gSourceSwapped=FALSE; BOOL gDestSwapped=FALSE; /* Conversion Options variables. */ DWORD gMBFlags = MB_PRECOMPOSED; DWORD gWCFlags = 0; char glpDefaultChar[4] = "?"; // what is max size of multibyte character? BOOL gUsedDefaultChar = FALSE; DWORD gTCSCMapStatus = DONOTMAP; //simplified and traditional Chinese mapping DWORD gFWHWMapStatus = DONOTMAP; //full width and half width mapping /* Handling the Byte Order Mark (BOM). * * If the input file begins with a BOM, then we know it is unicode, * we skip over the BOM and decrement the size of data by SIZEOFBOM. * * * Before writing data that we know is unicode, write the szBOM string * to the file. * * Notice that this means that the file sizes we show in the window * do NOT include the BOM. */ char szBOM[] = "\377\376"; // 0xFF, 0xFE // leave off TEXT() macro. char szRBOM[] = "\376\377"; // 0xFF, 0xFE // leave off TEXT() macro. UINT MBFlags = MB_OK | MB_ICONEXCLAMATION; TCHAR MBTitle[40]; TCHAR MBMessage[EXTENSION_LENGTH]; TCHAR szBlank[] = TEXT(""); TCHAR szNBytes[40]; TCHAR szFilter[MAX_PATH]; TCHAR szHelpPathName[] = TEXT("chnuconv.chm"); DLGTEMPLATE * dlgtSourceTab; DLGTEMPLATE * dlgtOptionTab; HGLOBAL hglbMem; PBYTE p; int NumCodePage; UINT uCodepage[]={ 0,//UNICODE 936, //GB 950,//BIG5 20000,//CNS 20001,//TCA 20002,//ETEN 20003,//IBM5 20004,//TELE 20005//WANG }; // // Module handle. // HANDLE _hModule; // // Application's icon handle. // HANDLE _hIcon; // // Main window handle. // HANDLE _hWndMain; HANDLE hMainTabControl; HANDLE hWndDisplay; HANDLE hWndTab[NUMBER_OF_PAGES]; // // Application's accelerator table handle. // HANDLE _hAccel; BOOL InitializeApplication( HINSTANCE hInstance, HINSTANCE hPrevInstance); BOOL MakeTabs( IN HWND hWnd, IN HWND hMainTabControl ); VOID AdjustSelectTab ( IN HWND hWnd, IN HWND hMainTabControl ); LRESULT APIENTRY MainWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); VOID CreateFilter(PTCHAR); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) /*++ Routine Description: Main is the entry point for Code Converter. It initializes the application and manages the message pump. When the message pump quits, main performs some global cleanup. Arguments: None. Return Value: int - Returns the result of the PostQuitMessgae API or -1 if initialization failed. --*/ { MSG msg; BOOL bHandled=FALSE; UNREFERENCED_PARAMETER( lpCmdLine ); UNREFERENCED_PARAMETER( nCmdShow ); if( InitializeApplication(hInstance, hPrevInstance)) { while( GetMessage( &msg, NULL, 0, 0 )) { bHandled = TranslateAccelerator( _hWndMain, _hAccel, &msg ); if (bHandled==FALSE) { bHandled = TranslateAccelerator(hWndDisplay, _hAccel, &msg); if (bHandled == FALSE && IsDialogMessage(_hWndMain, &msg)==FALSE) { TranslateMessage(&msg); // Translates virtual key codes DispatchMessage(&msg); // Dispatches message to window } } } return (int)msg.wParam; } // // Initialization failed. // return -1; } BOOL InitializeApplication( HINSTANCE hInstance, HINSTANCE hPrevInstance ) /*++ Routine Description: InitializeApplication does just what its name implies. It initializes global varaibles, sets up global state (e.g. 3D-Controls), registers window classes and creates and shows the application's main window. Arguments: None. Return Value: BOOL - Returns TRUE if the application succesfully initialized. --*/ { WNDCLASS Wc; TCHAR szBuffer[MAX_PATH]; TCHAR szBuf[400]; int i; // // Get the application's module (instance) handle. // InitCommonControls(); //_hModule = hInstance; _hModule = GetModuleHandle( NULL ); if( _hModule == NULL ) { return FALSE; } // // Load the application's main icon resource. // _hIcon = LoadIcon( _hModule, MAKEINTRESOURCE( IDI_CHNUCONV )); if( _hIcon == NULL ) { return FALSE; } // // Load the application's accelerator table. // _hAccel = LoadAccelerators( _hModule, MAKEINTRESOURCE( IDA_CHNUCONV )); if( _hAccel == NULL ) { return FALSE; } // // Register the window class for the application. // if (!hPrevInstance){ Wc.style = CS_HREDRAW | CS_OWNDC | CS_SAVEBITS | CS_VREDRAW; Wc.lpfnWndProc = MainWndProc; Wc.cbClsExtra = 0; Wc.cbWndExtra = DLGWINDOWEXTRA; Wc.hInstance = _hModule; Wc.hIcon = _hIcon; Wc.hCursor = LoadCursor( NULL, IDC_ARROW ); Wc.hbrBackground = ( HBRUSH ) ( COLOR_BTNFACE + 1 ); Wc.lpszMenuName = NULL; Wc.lpszClassName = L"Converter"; if (!RegisterClass( &Wc )) return FALSE; } for(i=0;icx )/2, ( ScreenHeight - (( LPCREATESTRUCT ) lParam )->cy )/2, 0, 0, SWP_NOSIZE | SWP_NOREDRAW | SWP_NOZORDER )) return 0; } case WM_INITDIALOG: { // // Get the handle of the tab control // hMainTabControl = GetDlgItem( hWnd, IDC_MAIN_TAB ); // // Fill out tab control with appropriate tabs // MakeTabs( hWnd, hMainTabControl ); hWndTab[0] = CreateDialogIndirect( _hModule, dlgtSourceTab, hWnd, SourceTabProc ); hWndTab[1]= CreateDialogIndirect( _hModule, dlgtSourceTab, hWnd, TargetTabProc ); hWndTab[2] = CreateDialogIndirect( _hModule, dlgtOptionTab, hWnd, OptionTabProc ); hWndDisplay=hWndTab[0]; ShowWindow(hWndDisplay, SW_SHOW); return( TRUE ); } case WM_COMMAND: { switch (LOWORD(wParam)) { /******************************************************************\ * WM_COMMAND, IDC_PUSH_CONVERT * * This is where the conversion actually takes place. * In either case, make the call twice. Once to determine how * much memory is needed, allocate space, and then make the call again. * * If conversion succeeds, it fills pDestinationData. \******************************************************************/ case IDC_PUSH_CONVERT: { int nBytesNeeded, nWCharNeeded, nWCharSource; TCHAR szSourceName[256]; int ConfirmMap; int i; GetSettings(); SwapSource(FALSE); if (nBytesSource == NODATA ) { LoadString(_hModule,IDS_NOTEXTCONVERT,MBMessage,EXTENSION_LENGTH); MessageBox (hWnd, MBMessage,MBTitle, MBFlags); return 0; } /* Converting UNICODE -> giDestinationCodePage*/ if (gTypeSource == TYPEUNICODE) { nWCharSource = nBytesSource/2; /* Allocate the required amount of space, including trailing NULL */ pTempData1= ManageMemory (MMALLOC, MMDESTINATION, nBytesSource, pTempData1); // Map string if we need to do TC-SC conversion. if (gTCSCMapStatus != DONOTMAP){ LCMapString (GetUserDefaultLCID(),gTCSCMapStatus, (LPWSTR)pSourceData,nWCharSource, (LPWSTR)pTempData1,nWCharSource); }else{ // no conversion, just copy things over. memcpy(pTempData1,pSourceData,nBytesSource); } // Map string if we need to do FW-HW conversion. if (gFWHWMapStatus != DONOTMAP){ pTempData= ManageMemory (MMALLOC, MMDESTINATION, nBytesSource, pTempData); LCMapString (GetUserDefaultLCID(),gFWHWMapStatus, (LPWSTR)pTempData1,nWCharSource, (LPWSTR)pTempData,nWCharSource); memcpy(pTempData1,pTempData,nBytesSource); } /*TS/SC mapping could happen between Unicode */ if (gTypeDest == TYPEUNICODE){ pDestinationData= ManageMemory (MMALLOC, MMDESTINATION, nBytesSource+2, pDestinationData); //put mapped unicode buffer to destination buffer. memcpy(pDestinationData,pTempData1,nBytesSource); nBytesDestination=nBytesSource; /* Unicode Null terminate string. */ pDestinationData[nBytesDestination] = 0; pDestinationData[nBytesDestination+1] = 0; }else{ giDestinationCodePage=uCodepage[gTypeDestID]; /*Query the number of bytes required to store the Dest string */ nBytesNeeded = WideCharToMultiByte(giDestinationCodePage, gWCFlags, (LPWSTR)pTempData1, nWCharSource, NULL, 0, glpDefaultChar, &gUsedDefaultChar); pDestinationData= ManageMemory (MMALLOC, MMDESTINATION, nBytesNeeded +1, pDestinationData); /* Do the conversion */ nBytesDestination = WideCharToMultiByte(giDestinationCodePage, gWCFlags, (LPWSTR)pTempData1, nWCharSource, (LPSTR)pDestinationData, nBytesNeeded, glpDefaultChar, &gUsedDefaultChar); /* Null terminate string. */ pDestinationData[nBytesDestination] = 0; } } /* converting giSourceCodePage -> UNICODE */ else if (gTypeSource == TYPECODEPAGE && gTypeDest == TYPEUNICODE) { giSourceCodePage=uCodepage[gTypeSourceID]; /* Query the number of WChar required to store the Dest string */ nWCharNeeded = MultiByteToWideChar(giSourceCodePage, gMBFlags, pSourceData, nBytesSource, NULL, 0 ); /* Allocate the required amount of space, including trailing NULL */ pDestinationData= ManageMemory (MMALLOC, MMDESTINATION, (nWCharNeeded +1)*2, pDestinationData); /* Do the conversion */ nWCharNeeded = MultiByteToWideChar(giSourceCodePage, gMBFlags, pSourceData, nBytesSource, (LPWSTR)pDestinationData, nWCharNeeded); /* MultiByteToWideChar returns # WCHAR, so multiply by 2 */ nBytesDestination = 2*nWCharNeeded ; // Decide if we need to do TC-SC conversion. if (gTCSCMapStatus != DONOTMAP) { pTempData1= ManageMemory (MMALLOC, MMDESTINATION, nBytesDestination, pTempData1); LCMapString (GetUserDefaultLCID(),gTCSCMapStatus, (LPWSTR)pDestinationData,nWCharNeeded, (LPWSTR)pTempData1,nWCharNeeded); memcpy(pDestinationData,pTempData1,nBytesDestination); } if (gFWHWMapStatus != DONOTMAP) { pTempData1= ManageMemory (MMALLOC, MMDESTINATION, nBytesDestination, pTempData1); LCMapString (GetUserDefaultLCID(),gFWHWMapStatus, (LPWSTR)pDestinationData,nWCharNeeded, (LPWSTR)pTempData1,nWCharNeeded); memcpy(pDestinationData,pTempData1,nBytesDestination); } /* Null terminate string. */ pDestinationData[nBytesDestination] = 0; // UNICODE_NULL pDestinationData[nBytesDestination+1] = 0; /* converting giSourceCodePage -> giDestinationCodePage */ } else if(gTypeSourceID < NumCodePage && gTypeDestID < NumCodePage){ giSourceCodePage=uCodepage[gTypeSourceID]; /* Query the number of WChar required to store the Dest string */ nWCharNeeded = MultiByteToWideChar(giSourceCodePage, gMBFlags, pSourceData, nBytesSource, NULL, 0 ); /* Allocate the required amount of space, including trailing NULL */ pTempData= ManageMemory (MMALLOC, MMDESTINATION, (nWCharNeeded +1)*2, pTempData); /* Do the conversion */ nWCharNeeded = MultiByteToWideChar(giSourceCodePage, gMBFlags, pSourceData, nBytesSource, (LPWSTR)pTempData, nWCharNeeded); /* MultiByteToWideChar returns # WCHAR, so multiply by 2 */ nBytesTemp = 2*nWCharNeeded ; // Decide if we need to do TC-SC conversion. if (gTCSCMapStatus != DONOTMAP) { pTempData1= ManageMemory (MMALLOC, MMDESTINATION, nBytesTemp, pTempData1); LCMapString (GetUserDefaultLCID(),gTCSCMapStatus, (LPWSTR)pTempData,nWCharNeeded, (LPWSTR)pTempData1,nWCharNeeded); memcpy(pTempData,pTempData1,nBytesTemp); } if (gFWHWMapStatus != DONOTMAP) { pTempData1= ManageMemory (MMALLOC, MMDESTINATION, nBytesTemp, pTempData1); LCMapString (GetUserDefaultLCID(),gFWHWMapStatus, (LPWSTR)pTempData,nWCharNeeded, (LPWSTR)pTempData1,nWCharNeeded); memcpy(pTempData,pTempData1,nBytesTemp); } /* Null terminate string. */ pTempData[nBytesTemp] = 0; // UNICODE_NULL pTempData[nBytesTemp+1] = 0; giDestinationCodePage=uCodepage[gTypeDestID]; nWCharSource = nBytesTemp/2; /* Query the number of bytes required to store the Dest string */ nBytesNeeded = WideCharToMultiByte(giDestinationCodePage, gWCFlags, (LPWSTR)pTempData, nWCharSource, NULL, 0, glpDefaultChar, &gUsedDefaultChar); /* Allocate the required amount of space, including trailing NULL */ pDestinationData= ManageMemory (MMALLOC, MMDESTINATION, nBytesNeeded +1, pDestinationData); /* Do the conversion */ nBytesDestination = WideCharToMultiByte(giDestinationCodePage, gWCFlags, (LPWSTR)pTempData, nWCharSource, pDestinationData, nBytesNeeded, glpDefaultChar, &gUsedDefaultChar); /* Null terminate string. */ pDestinationData[nBytesDestination] = 0; } else { LoadString(_hModule,IDS_STYPEUNKNOWN,MBMessage,EXTENSION_LENGTH); MessageBox (hWnd, MBMessage,MBTitle, MBFlags); return 0; } /* code common to all conversions... */ LoadString(_hModule, IDS_NOTSAVEYET, szBuffer, 50); TabCtrl_SetCurSel(hMainTabControl, 1); AdjustSelectTab(hWnd, hMainTabControl); SetDlgItemText (hWndTab[1], IDC_NAMETEXT, szBuffer); wsprintf (szBuffer, szNBytes, nBytesDestination); SetDlgItemText (hWndTab[1], IDC_SIZETEXT, szBuffer); EnableControl(hWndTab[1], IDC_OPENORSAVEAS, TRUE); EnableControl(hWndTab[1], IDC_VIEW, TRUE); EnableControl(hWndTab[1], IDC_PASTEORCOPY, TRUE); EnableControl(hWndTab[1], IDC_CLEAR, TRUE); EnableControl(hWndTab[1], IDC_SWAPHIGHLOW, TRUE); EnableMenuItem (GetMenu (_hWndMain),IDM_FILE_SAVEAS,MF_ENABLED); break; // end case IDC_PUSH_CONVERT } case IDM_HELP_CONTENT: case IDC_PUSH_HELP: { HtmlHelp(hWnd,szHelpPathName, HH_DISPLAY_TOPIC, (DWORD_PTR) NULL ); break; } case IDM_HELP_ABOUT: { LoadString(_hModule, IDS_APPLICATION_NAME,szBuffer, EXTENSION_LENGTH); ShellAbout (hWnd, szBuffer, TEXT(""), _hIcon ); break; } break; case IDM_FILE_OPEN: { SendMessage(hWndTab[0], WM_COMMAND, IDC_OPENORSAVEAS,0); break; } case IDM_FILE_SAVEAS: { SendMessage(hWndTab[1], WM_COMMAND, IDC_OPENORSAVEAS,0); break; } case IDM_FILE_EXIT: case IDOK: PostMessage(hWnd, WM_CLOSE, 0, 0L); break; default: return FALSE; } break; } case WM_NOTIFY: { static int nPreviousTab = 1; // switch on notification code switch ( ((LPNMHDR)lParam)->code ) { case TCN_SELCHANGE: { AdjustSelectTab(hWnd, hMainTabControl); return(TRUE); } } break; } case WM_CLOSE: { DestroyWindow( hWnd ); break; } case WM_DESTROY: { // WinHelp( hwnd, szHelpPathName, (UINT) HELP_QUIT, (DWORD) NULL ); ManageMemory (MMFREE, MMDESTINATION, 0, pTempData1); ManageMemory (MMFREE, MMSOURCE, 0, pSourceData); ManageMemory (MMFREE, MMDESTINATION, 0, pDestinationData); ManageMemory (MMFREE, MMSOURCE, 0, pViewSourceData); ManageMemory (MMFREE, MMDESTINATION, 0, pTempData); GlobalUnlock(hglbMem); GlobalFree(hglbMem); // // Destroy the application. // PostQuitMessage(0); return 0; } default: break; } return DefWindowProc( hWnd, message, wParam, lParam ); } INT_PTR OptionTabProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_INITDIALOG: { RECT rcTab; //GetTab window size // first get the size of the tab control if (GetWindowRect( hMainTabControl, &rcTab )){ // adjust it to compensate for the tabs TabCtrl_AdjustRect( hMainTabControl, FALSE , &rcTab); // convert the screen coordinates to client coordinates MapWindowPoints( HWND_DESKTOP, GetParent(hMainTabControl), (LPPOINT)&rcTab, 2); } SetWindowPos(hWnd, HWND_TOP, rcTab.left, rcTab.top, rcTab.right - rcTab.left, rcTab.bottom - rcTab.top, SWP_NOACTIVATE ); SendDlgItemMessage(hWnd, IDC_NOSCTCMAP, BM_SETCHECK, 1, 0); SendDlgItemMessage(hWnd, IDC_NOHWFWMAP, BM_SETCHECK, 1, 0); return(FALSE); } case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_RESET : { SendDlgItemMessage(hWnd, IDC_NOSCTCMAP, BM_SETCHECK, 1, 0); SendDlgItemMessage(hWnd, IDC_SCTCMAP, BM_SETCHECK, 0, 0); SendDlgItemMessage(hWnd, IDC_TCSCMAP, BM_SETCHECK, 0, 0); SendDlgItemMessage(hWnd, IDC_NOHWFWMAP, BM_SETCHECK, 1, 0); SendDlgItemMessage(hWnd, IDC_HWFWMAP, BM_SETCHECK, 0, 0); SendDlgItemMessage(hWnd, IDC_FWHWMAP, BM_SETCHECK, 0, 0); } break; } } default: break; } return DefWindowProc( hWnd, message, wParam, lParam ); } VOID GetSettings() { int i; gTypeSource = TYPEUNKNOWN; //Get source settings. for(i=0;i