|
|
/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
Chcp
Abstract:
Chcpo is a DOS5-Compatible codepage utility
Author:
Ramon Juan San Andres (ramonsa) 01-May-1991
Revision History:
--*/
#include "ulib.hxx"
#include "arg.hxx"
#include "stream.hxx"
#include "smsg.hxx"
#include "wstring.hxx"
#include "rtmsg.h"
#include "chcp.hxx"
VOID __cdecl main ( )
/*++
Routine Description:
Main function of the Chcp utility
Arguments:
None.
Return Value:
None.
Notes:
--*/
{ //
// Initialize stuff
//
DEFINE_CLASS_DESCRIPTOR( CHCP );
{ CHCP Chcp;
if ( Chcp.Initialize() ) {
Chcp.Chcp(); } } }
DEFINE_CONSTRUCTOR( CHCP, PROGRAM );
CHCP::~CHCP ( )
/*++
Routine Description:
Destructs a CHCP object
Arguments:
None.
Return Value:
None.
Notes:
--*/
{ }
BOOLEAN CHCP::Initialize ( )
/*++
Routine Description:
Initializes a CHCP object
Arguments:
None.
Return Value:
TRUE if initialized.
Notes:
--*/
{ //
// Initialize program object
//
if ( PROGRAM::Initialize( MSG_CHCP_USAGE ) && _Screen.Initialize( )
) {
_SetCodePage = FALSE; _CodePage = 0;
return TRUE;
}
return FALSE; }
BOOLEAN CHCP::Chcp ( )
/*++
Routine Description:
Does the Chcp thing.
Arguments:
None.
Return Value:
TRUE.
Notes:
--*/
{ ValidateVersion();
if ( ParseArguments() ) {
if ( _SetCodePage ) {
//
// Set the code page
//
if ( !SetCodePage() ) { ExitProgram( EXIT_ERROR ); }
} else {
//
// Display current code page
//
if ( !DisplayCodePage() ) { ExitProgram( EXIT_ERROR ); } }
ExitProgram( EXIT_NORMAL );
} else {
ExitProgram( EXIT_ERROR );
}
return TRUE; }
BOOLEAN CHCP::DisplayCodePage ( )
/*++
Routine Description:
Displays the active code page
Arguments:
None.
Return Value:
TRUE if success, FALSE if syntax error.
Notes:
--*/
{
DisplayMessage( MSG_CHCP_ACTIVE_CODEPAGE, NORMAL_MESSAGE, "%d", _Screen.QueryCodePage( ) );
return TRUE; }
BOOLEAN CHCP::ParseArguments ( )
/*++
Routine Description:
Parses arguments
Arguments:
None.
Return Value:
TRUE if success, FALSE if syntax error.
Notes:
--*/
{
ARGUMENT_LEXEMIZER ArgLex; ARRAY LexArray; ARRAY ArgArray;
STRING_ARGUMENT ProgramNameArgument; LONG_ARGUMENT CodePageArgument; FLAG_ARGUMENT UsageArgument;
if ( !ArgArray.Initialize() || !LexArray.Initialize() || !ArgLex.Initialize( &LexArray ) ) {
DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE ); ExitProgram( EXIT_ERROR ); }
if ( !ProgramNameArgument.Initialize( "*" ) || !UsageArgument.Initialize( "/?" ) || !CodePageArgument.Initialize( "*" ) ) {
DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE ); ExitProgram( EXIT_ERROR ); }
if ( !ArgArray.Put( &ProgramNameArgument ) || !ArgArray.Put( &UsageArgument ) || !ArgArray.Put( &CodePageArgument ) ) {
DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE ); ExitProgram( EXIT_ERROR ); }
//
// Set up the defaults
//
ArgLex.PutSwitches( "/" ); ArgLex.SetCaseSensitive( FALSE );
if ( !ArgLex.PrepareToParse() ) {
DisplayMessage( MSG_CHCP_INTERNAL_ERROR, ERROR_MESSAGE ); ExitProgram( EXIT_ERROR ); }
if ( !ArgLex.DoParsing( &ArgArray ) ) {
DisplayMessage( MSG_CHCP_INVALID_PARAMETER, ERROR_MESSAGE, "%W", ArgLex.QueryInvalidArgument() ); ExitProgram( EXIT_ERROR );
}
//
// Display Help if requested
//
if ( UsageArgument.IsValueSet() ) {
DisplayMessage( MSG_CHCP_USAGE, NORMAL_MESSAGE ); ExitProgram( EXIT_NORMAL );
}
if ( CodePageArgument.IsValueSet() ) {
_SetCodePage = TRUE; _CodePage = (DWORD)CodePageArgument.QueryLong();
} else {
_SetCodePage = FALSE; }
return TRUE; }
inline bool IsFarEastCodePage(UINT cp) { return cp == 932 || cp == 949 || cp == 936 || cp == 950; }
inline bool IsFarEastLocale(LANGID langid) { // Accepts primay langid only
return langid == LANG_JAPANESE || langid == LANG_KOREAN || langid == LANG_CHINESE; }
inline bool IsFarEastSystemLocale() { return IsFarEastLocale(PRIMARYLANGID(GetSystemDefaultLangID())); }
BOOLEAN CHCP::SetCodePage ( )
/*++
Routine Description:
Sets the active code page
Arguments:
None.
Return Value:
TRUE if success, FALSE if syntax error.
Notes:
--*/
{ UINT OldCP = _Screen.QueryCodePage( );
if (IsFarEastSystemLocale() && (IsFarEastCodePage(_CodePage) || IsFarEastCodePage(OldCP)) && _CodePage != OldCP) { /*
* This CLS function is needed only if it's FE. */ _Screen.MoveCursorTo(0, 0); _Screen.EraseScreenAndResetAttribute(); }
if ( _Screen.SetOutputCodePage( _CodePage ) ) { if (_Screen.SetCodePage( _CodePage ) ) {
// Comment from NT4J:
// Since FormatMessage checks the current TEB's locale, and the Locale for
// CHCP is initialized when the message class is initialized, the TEB has to
// be updated after the code page is changed successfully. All other code
// pages other than JP and US are ignored.
if (IsFarEastSystemLocale()) { LANGID LangId;
switch (_CodePage) { case 932: LangId = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT); break; case 949: LangId = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN); break; case 936: LangId = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED); break; case 950: LangId = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL); break; default: LangId = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); break; }
SetThreadLocale(MAKELCID(LangId, SORT_DEFAULT)); }
return DisplayCodePage( ); } else { // SetOutputCodePage failed.
// Restore the privous input code page
_Screen.SetOutputCodePage( OldCP ); } }
// Was unable to set the given code page
DisplayMessage( MSG_CHCP_INVALID_CODEPAGE, ERROR_MESSAGE ); return FALSE; }
|