852 lines
18 KiB
C++
852 lines
18 KiB
C++
/*++
|
||
|
||
Copyright (c) 1990-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
PAGER
|
||
|
||
Abstract:
|
||
|
||
This module contains the implementations for the PAGER class
|
||
|
||
Author:
|
||
|
||
Ramon Juan San Andres (RamonSA) 15-Apr-1990
|
||
|
||
Notes:
|
||
|
||
|
||
--*/
|
||
|
||
#include "ulib.hxx"
|
||
#include "filestrm.hxx"
|
||
#include "wstring.hxx"
|
||
#include "bstring.hxx"
|
||
#include "screen.hxx"
|
||
#include "stream.hxx"
|
||
#include "more.hxx"
|
||
#include "pager.hxx"
|
||
|
||
//
|
||
// What constitutes a "blank" character (spaces and tabs)
|
||
//
|
||
#define BLANKCHARACTERS (LPWSTR)L" \t"
|
||
#define TAB_ASCII (CHAR)'\t'
|
||
|
||
|
||
|
||
DEFINE_CONSTRUCTOR( PAGER, OBJECT );
|
||
|
||
VOID
|
||
PAGER::Construct (
|
||
)
|
||
{
|
||
UNREFERENCED_PARAMETER( this );
|
||
}
|
||
|
||
PAGER::~PAGER (
|
||
)
|
||
{
|
||
|
||
DELETE( _String );
|
||
DELETE( _BString );
|
||
DELETE( _Blanks );
|
||
DELETE( _BlankLine );
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
PAGER::Initialize (
|
||
IN PSTREAM Stream,
|
||
IN PPROGRAM Program
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Phase 2 of construction for a pager object. It initializes its
|
||
internal data.
|
||
|
||
Arguments:
|
||
|
||
Stream - Supplies the stream to be paged
|
||
Program - Supplies pointer to the program doing the paging.
|
||
|
||
Return Value:
|
||
|
||
TRUE - If initialized correctly
|
||
FALSE - If something when wrong. (check error stack)
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
USHORT ScreenRows, RowsInPage;
|
||
CHNUM i;
|
||
|
||
_Stream = Stream;
|
||
_CurrentLineNumber = 0;
|
||
_StandardOutput = Program->GetStandardOutput();
|
||
_Screen = SCREEN::Cast( _StandardOutput );
|
||
_Position = INVALID_CHNUM;
|
||
|
||
//
|
||
// Get the page dimensions
|
||
//
|
||
if (_Screen) {
|
||
_Screen->QueryScreenSize( &ScreenRows, &_ColumnsInScreen, &RowsInPage, &_ColumnsInPage );
|
||
_RowsInPage = RowsInPage;
|
||
_ColumnsInPage = _ColumnsInScreen;
|
||
} else {
|
||
|
||
// If we don't have a screen then we should treat the page
|
||
// as infinitely long since we have no need to prompt.
|
||
|
||
_RowsInPage = (ULONG) -1;
|
||
_ColumnsInPage = (USHORT) -1;
|
||
}
|
||
|
||
if (!(_String = NEW DSTRING) ||
|
||
!(_BString = NEW BDSTRING) ||
|
||
!(_Blanks = NEW DSTRING) ||
|
||
!(_BlankLine = NEW DSTRING) ||
|
||
!_String->Initialize() ||
|
||
!_BString->Initialize() ||
|
||
!_Blanks->Initialize(BLANKCHARACTERS) ||
|
||
!_BlankLine->Resize(_Screen ? _ColumnsInPage : 0)) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
for (i = 0; i < _BlankLine->QueryChCount(); i++) {
|
||
_BlankLine->SetChAt(' ', i);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
BOOLEAN
|
||
PAGER::DisplayPage (
|
||
IN ULONG LinesInPage,
|
||
IN BOOLEAN ClearScreen,
|
||
IN BOOLEAN SqueezeBlankLines,
|
||
IN BOOLEAN ExpandFormFeed,
|
||
IN ULONG TabExp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Displays a page of the screen
|
||
|
||
Arguments:
|
||
|
||
LinesInPage - Supplies the desired number of lines in the page
|
||
ClearScreen - Supplies a flag, which if TRUE means that we
|
||
want to clear the screen before displaying the
|
||
page
|
||
SqueezeBlankLines - Supplies squeeze flag
|
||
ExpandFormFeed - Supplies formfeed expansion flag
|
||
|
||
Return Value:
|
||
|
||
TRUE - If page displayed
|
||
FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG LinesLeft = LinesInPage;
|
||
BOOLEAN IgnoreBlankLine = FALSE;
|
||
CHNUM Length;
|
||
CHNUM FormFeedAt;
|
||
|
||
|
||
if ( TabExp > (ULONG)( _ColumnsInPage - 1 ) ) {
|
||
TabExp = _ColumnsInPage - 1 ;
|
||
}
|
||
|
||
//
|
||
// Clear the screen if instructed to do so
|
||
//
|
||
if ( ClearScreen && _Screen) {
|
||
#ifdef FE_SB // v-junm - 08/18/93
|
||
// Also reset attributes.
|
||
_Screen->EraseScreenAndResetAttribute();
|
||
#else
|
||
_Screen->EraseScreen();
|
||
#endif
|
||
_Screen->MoveCursorTo( 0, 0 );
|
||
} else {
|
||
//
|
||
// Make sure that we start at the beginning of a line
|
||
//
|
||
ClearLine();
|
||
}
|
||
|
||
//
|
||
// Display up to LinesLeft lines
|
||
//
|
||
|
||
while ( LinesLeft > 0 &&
|
||
(ThereIsMoreToPage() || _Position != INVALID_CHNUM) ) {
|
||
|
||
//
|
||
// Get next string from input
|
||
//
|
||
if (!ReadNextString( TabExp )) {
|
||
return FALSE;
|
||
}
|
||
|
||
#ifdef FE_SB // v-junm - 08/18/93
|
||
// Now QueryChCount returns the correct number of unicode chars. An additional
|
||
// API, QueryByteCount was added.
|
||
Length = _String->QueryByteCount() - _Position;
|
||
#else
|
||
Length = _String->QueryChCount() - _Position;
|
||
#endif
|
||
|
||
if ( SqueezeBlankLines ) {
|
||
|
||
if ( _String->Strspn( _Blanks, _Position ) == INVALID_CHNUM ) {
|
||
|
||
//
|
||
// This is a blank line. We must sqeeze
|
||
//
|
||
if ( IgnoreBlankLine ) {
|
||
//
|
||
// We ignore the line
|
||
//
|
||
_Position = INVALID_CHNUM;
|
||
continue;
|
||
|
||
} else {
|
||
//
|
||
// We will print a blank line and ignore the following
|
||
// blank lines.
|
||
//
|
||
DisplayBlankLine( 1 );
|
||
_Position = INVALID_CHNUM;
|
||
IgnoreBlankLine = TRUE;
|
||
continue;
|
||
}
|
||
} else if (IgnoreBlankLine) {
|
||
LinesLeft--;
|
||
IgnoreBlankLine = FALSE;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
|
||
if ( ExpandFormFeed ) {
|
||
//
|
||
// Look for form feed within line
|
||
//
|
||
if ((FormFeedAt = _String->Strchr( FORMFEED,_Position )) != INVALID_CHNUM) {
|
||
if ( FormFeedAt == _Position ) {
|
||
//
|
||
// First character is a form feed.
|
||
//
|
||
// We will skip the formfeed character, and the
|
||
// rest of the screen will be blanked.
|
||
//
|
||
if ( SqueezeBlankLines ) {
|
||
if (!IgnoreBlankLine) {
|
||
DisplayBlankLine( 1 );
|
||
LinesLeft--;
|
||
IgnoreBlankLine = TRUE;
|
||
}
|
||
} else {
|
||
DisplayBlankLine( LinesLeft );
|
||
LinesLeft = 0;
|
||
}
|
||
_Position++;
|
||
continue;
|
||
}
|
||
|
||
Length = FormFeedAt - _Position;
|
||
}
|
||
}
|
||
|
||
|
||
//
|
||
// If the line is too long, we must split it
|
||
//
|
||
if (Length > (CHNUM)_ColumnsInPage) {
|
||
Length = (CHNUM)_ColumnsInPage;
|
||
}
|
||
|
||
//
|
||
// Display the string
|
||
//
|
||
DisplayString( _String, &_Position, Length );
|
||
IgnoreBlankLine = FALSE;
|
||
|
||
LinesLeft--;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
VOID
|
||
PAGER::ClearLine (
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Clears a line
|
||
|
||
Arguments:
|
||
|
||
none
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT ScreenRows, ScreenCols;
|
||
USHORT WindowRows, WindowCols;
|
||
CHNUM i;
|
||
|
||
if (_Screen) {
|
||
|
||
_Screen->QueryScreenSize( &ScreenRows,
|
||
&ScreenCols,
|
||
&WindowRows,
|
||
&WindowCols );
|
||
//
|
||
// If the number of columns has changed, re-initialize the
|
||
// blank line.
|
||
//
|
||
if ( ScreenCols != _ColumnsInPage ) {
|
||
_BlankLine->Resize(ScreenCols);
|
||
for (i = 0; i < ScreenCols; i++) {
|
||
_BlankLine->SetChAt(' ', i);
|
||
}
|
||
}
|
||
_RowsInPage = WindowRows;
|
||
_ColumnsInPage = ScreenCols;
|
||
|
||
_StandardOutput->WriteChar( (WCHAR)CARRIAGERETURN );
|
||
_StandardOutput->WriteString( _BlankLine, 0, _ColumnsInPage-1 );
|
||
_StandardOutput->WriteChar( (WCHAR)CARRIAGERETURN );
|
||
}
|
||
}
|
||
|
||
VOID
|
||
PAGER::DisplayBlankLine (
|
||
IN ULONG Lines,
|
||
IN BOOLEAN NewLine
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Displays a number of blank lines
|
||
|
||
Arguments:
|
||
|
||
Lines - Supplies the number of blank lines to display
|
||
NewLine - Supplies the newline flag
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
|
||
{
|
||
CHNUM Position;
|
||
|
||
while ( Lines-- ) {
|
||
|
||
Position = 0;
|
||
|
||
DisplayString( _BlankLine, &Position, _ColumnsInPage-1, (Lines > 0) ? TRUE : NewLine);
|
||
|
||
}
|
||
}
|
||
|
||
VOID
|
||
PAGER::DisplayString (
|
||
IN PWSTRING String,
|
||
OUT PCHNUM Position,
|
||
IN CHNUM Length,
|
||
IN BOOLEAN NewLine
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Displays a chunk of the current string
|
||
|
||
Arguments:
|
||
|
||
Length - Supplies the length of the string to display
|
||
NewLine - Supplies the newline flag
|
||
|
||
Return Value:
|
||
|
||
none
|
||
|
||
--*/
|
||
|
||
{
|
||
#ifdef FE_SB // v-junm - 04/19/93
|
||
|
||
CHNUM UnicodeCharNum, // # of unicode characters to display
|
||
TempByteCount, // to minimize calls to QueryByteCount
|
||
index; // loop counter
|
||
PSTR STRBuffer; // ASCIIZ converted string pointer
|
||
static CHNUM OldPos; // Keeps old position in # of Unicode
|
||
BOOL DBCSFlag = FALSE; // Flag for ending leadbyte
|
||
|
||
TempByteCount = String->QueryByteCount();
|
||
Length = min( Length, TempByteCount );
|
||
|
||
// If the length of the string to display is shorter than
|
||
// the width of the screen, we do not have to do any DBCS
|
||
// checking. Just print it out. (Can be skipped for CP437)
|
||
//
|
||
|
||
if ( TempByteCount > _ColumnsInPage ) {
|
||
|
||
//
|
||
// Initialize # of unicode characters to #
|
||
// of ASCII chars to display.
|
||
//
|
||
|
||
UnicodeCharNum = Length;
|
||
|
||
//
|
||
// Get the string as a ASCIIZ text.
|
||
//
|
||
|
||
STRBuffer = String->QuerySTR();
|
||
|
||
if ( STRBuffer != NULL ) {
|
||
|
||
//
|
||
// Start changing the UnicodeCharNum from the actual
|
||
// number of bytes to the actual number of characters.
|
||
//
|
||
|
||
for( index = 0; index < Length; index++ ) {
|
||
if ( IsLeadByte( *(STRBuffer + index + _Position) ) ) {
|
||
index++;
|
||
UnicodeCharNum--;
|
||
DBCSFlag = TRUE;
|
||
}
|
||
else
|
||
DBCSFlag = FALSE;
|
||
}
|
||
DELETE( STRBuffer );
|
||
}
|
||
|
||
//
|
||
// If the following conditions are true, then there
|
||
// is a Leadbyte at the end of the screen that needs
|
||
// to be displayed on the next line with it's tail byte.
|
||
//
|
||
|
||
if ( DBCSFlag == TRUE && // String ends with DBCS.
|
||
index == (Length - 1) && // Only Leadbyte.
|
||
Length == (CHNUM)_ColumnsInPage // More rows to display.
|
||
) {
|
||
Length--;
|
||
UnicodeCharNum--;
|
||
}
|
||
|
||
}
|
||
else
|
||
//fix kksuzuka: #195
|
||
//Overflow pagecolumns when writing 0D0A.
|
||
//UnicodeCharNum = String->QueryChCount();
|
||
UnicodeCharNum = min( Length, String->QueryChCount() );
|
||
|
||
//
|
||
// When the string does not fit on one line and needs to be truncated,
|
||
// OldPos keeps the position where the string was truncated in Unicode
|
||
// location.
|
||
//
|
||
|
||
|
||
//
|
||
// If true, set to beginning of string.
|
||
//
|
||
|
||
if ( *Position == 0 )
|
||
OldPos = 0;
|
||
|
||
_StandardOutput->WriteString( String, OldPos, UnicodeCharNum );
|
||
|
||
//
|
||
// Set to last+1 char displayed in unicode character numbers.
|
||
//
|
||
|
||
OldPos += UnicodeCharNum;
|
||
|
||
//
|
||
// Update our position within the string
|
||
//
|
||
|
||
*Position += Length;
|
||
|
||
//
|
||
// Check if all the characters have been written.
|
||
//
|
||
|
||
if ( TempByteCount && (TempByteCount == *Position) &&
|
||
!(TempByteCount % _ColumnsInPage) ) {
|
||
|
||
//
|
||
// Characters have been written, but there is a LF/CR
|
||
// character at the that needs to be display that has
|
||
// not been displayed. (At _ColumnsInPage+1 location)
|
||
//
|
||
|
||
*Position = INVALID_CHNUM;
|
||
// _StandardOutput->WriteChar( (WCHAR)CARRIAGERETURN );
|
||
// _StandardOutput->WriteChar( (WCHAR)LINEFEED );
|
||
|
||
}
|
||
else if ( *Position >= TempByteCount )
|
||
*Position = INVALID_CHNUM;
|
||
|
||
if ( ((*Position != INVALID_CHNUM) || NewLine) &&
|
||
( Length < _ColumnsInScreen || !_Screen ) ) {
|
||
|
||
_StandardOutput->WriteChar( (WCHAR)CARRIAGERETURN );
|
||
_StandardOutput->WriteChar( (WCHAR)LINEFEED );
|
||
}
|
||
|
||
#else // FE_SB
|
||
|
||
Length = min( Length, String->QueryChCount() );
|
||
|
||
_StandardOutput->WriteString( String, *Position, Length );
|
||
|
||
//
|
||
// Update our position within the string
|
||
//
|
||
*Position += Length;
|
||
|
||
if (*Position >= _String->QueryChCount()) {
|
||
*Position = INVALID_CHNUM;
|
||
}
|
||
|
||
if ( ((*Position != INVALID_CHNUM) || NewLine) &&
|
||
( Length < _ColumnsInScreen || !_Screen ) ) {
|
||
_StandardOutput->WriteChar( (WCHAR)CARRIAGERETURN );
|
||
_StandardOutput->WriteChar( (WCHAR)LINEFEED );
|
||
}
|
||
|
||
#endif
|
||
}
|
||
|
||
|
||
ULONGLONG
|
||
PAGER::QueryCurrentByte (
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Queries the current Byte number
|
||
|
||
Arguments:
|
||
|
||
none
|
||
|
||
Return Value:
|
||
|
||
The current byte number
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
PFILE_STREAM pFileStream;
|
||
ULONGLONG PointerPosition ;
|
||
|
||
if ((pFileStream = FILE_STREAM::Cast(_Stream)) == NULL ) {
|
||
|
||
return 0;
|
||
|
||
} else {
|
||
|
||
pFileStream->QueryPointerPosition( &PointerPosition );
|
||
|
||
return PointerPosition;
|
||
}
|
||
}
|
||
|
||
USHORT
|
||
PAGER::QueryLinesPerPage (
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Queries the number of lines per page of output
|
||
|
||
Arguments:
|
||
|
||
none
|
||
|
||
Return Value:
|
||
|
||
The number of lines (rows) in a page
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT ScreenRows, ScreenCols;
|
||
USHORT WindowRows, WindowCols;
|
||
CHNUM i;
|
||
|
||
//
|
||
// If Paging to screen, get the current size of the window
|
||
//
|
||
if (_Screen) {
|
||
|
||
_Screen->QueryScreenSize( &ScreenRows,
|
||
&ScreenCols,
|
||
&WindowRows,
|
||
&WindowCols );
|
||
//
|
||
// If the number of columns has changed, re-initialize the
|
||
// blank line.
|
||
//
|
||
if ( WindowCols != _ColumnsInPage ) {
|
||
_BlankLine->Resize(ScreenCols);
|
||
for (i = 0; i < ScreenCols; i++) {
|
||
_BlankLine->SetChAt(' ', i);
|
||
}
|
||
}
|
||
_RowsInPage = WindowRows;
|
||
_ColumnsInPage = ScreenCols;
|
||
}
|
||
|
||
return (USHORT)_RowsInPage;
|
||
}
|
||
|
||
BOOLEAN
|
||
PAGER::ReadNextString (
|
||
IN ULONG TabExp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads in the next string from the input stream.
|
||
|
||
Arguments:
|
||
|
||
TabExp - Supplies the number of blank characters per tab
|
||
|
||
Return Value:
|
||
|
||
TRUE - If string read in
|
||
FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
if (_Position == INVALID_CHNUM ) {
|
||
|
||
CHNUM Idx;
|
||
|
||
//
|
||
// We have to read a new string from the input stream.
|
||
//
|
||
if (!_Stream->ReadLine( _String )) {
|
||
return FALSE;
|
||
}
|
||
|
||
_CurrentLineNumber++;
|
||
_Position = 0;
|
||
|
||
//
|
||
// Expand tabs
|
||
//
|
||
Idx = 0;
|
||
|
||
//
|
||
// Get the string as a ASCIIZ text.
|
||
//
|
||
PSTR szBuffer; // ASCIIZ converted string pointer
|
||
|
||
szBuffer = _String->QuerySTR();
|
||
if (szBuffer != NULL) {
|
||
_BString->Initialize(szBuffer);
|
||
DELETE( szBuffer );
|
||
|
||
while ( (Idx < _BString->QueryChCount()) &&
|
||
((Idx = _BString->Strchr( TAB_ASCII, Idx )) != INVALID_CHNUM) ) {
|
||
|
||
if (TabExp) {
|
||
_BString->ReplaceWithChars(
|
||
Idx, // AtPosition
|
||
1, // AtLength
|
||
' ', // Replacement char
|
||
TabExp - Idx%TabExp // FromLength
|
||
);
|
||
} else {
|
||
_BString->ReplaceWithChars(
|
||
Idx, // AtPosition
|
||
1, // AtLength
|
||
' ', // Replacement char
|
||
0 // FromLength
|
||
);
|
||
}
|
||
|
||
//
|
||
// MJB: If we're eliminating tabs we don't want to advance the
|
||
// index; removing the previous tab has pulled the next character
|
||
// in *to* the index, so it's already where we want it. Advancing
|
||
// regardless can cause every other adjacent tab not to be
|
||
// elminiated.
|
||
//
|
||
|
||
if (TabExp > 0) {
|
||
Idx = _BString->NextChar(Idx);
|
||
}
|
||
}
|
||
|
||
szBuffer = _BString->QuerySTR();
|
||
if (szBuffer != NULL) {
|
||
_String->Initialize(szBuffer);
|
||
DELETE( szBuffer );
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
PAGER::SkipLines (
|
||
IN ULONG LinesToSkip,
|
||
IN ULONG TabExp
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Skips certain number of lines
|
||
|
||
Arguments:
|
||
|
||
LinesToSkip - Supplies the number of lines to skip
|
||
TabExp - Supplies number of spaces per tab
|
||
|
||
Return Value:
|
||
|
||
TRUE - If lines skipped
|
||
FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
if ( TabExp > (ULONG)( _ColumnsInPage - 1 ) ) {
|
||
TabExp = _ColumnsInPage - 1;
|
||
}
|
||
|
||
while ( LinesToSkip-- && ThereIsMoreToPage() ) {
|
||
|
||
if (!ReadNextString( TabExp )) {
|
||
return FALSE;
|
||
}
|
||
|
||
_Position = INVALID_CHNUM;
|
||
|
||
}
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
#ifdef FE_SB // v-junm - 09/24/93
|
||
|
||
BOOLEAN
|
||
PAGER::IsLeadByte(
|
||
IN BYTE c
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks to see if c is a leadbyte of a DBCS character.
|
||
|
||
Arguments:
|
||
|
||
c - character to check to see if leadbyte.
|
||
|
||
Return Value:
|
||
|
||
TRUE - leadbyte of DBCS character.
|
||
FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
CPINFO cp;
|
||
static UINT outputcp = GetConsoleOutputCP();
|
||
int i;
|
||
|
||
if ( GetCPInfo( outputcp, &cp ) ) {
|
||
|
||
//
|
||
// Code page info has been aquired. From code page info,
|
||
// the leadbyte range can be determined.
|
||
//
|
||
|
||
for( i = 0; cp.LeadByte[i] && cp.LeadByte[i+1]; i += 2 ) {
|
||
|
||
//
|
||
// There are leadbytes. Check to see if c falls in
|
||
// current leadbyte range.
|
||
//
|
||
|
||
if ( c >= cp.LeadByte[i] && c <= cp.LeadByte[i+1] )
|
||
return( TRUE );
|
||
|
||
}
|
||
|
||
return( FALSE );
|
||
}
|
||
else {
|
||
|
||
//
|
||
// This will not produce correct results if
|
||
// 'ConsoleOutputCP != SystemCP && DBCS System'
|
||
// Just making system conversion the default
|
||
// when GetCPInfo doesn't work.
|
||
//
|
||
|
||
return( IsDBCSLeadByte( c ) != FALSE );
|
||
}
|
||
}
|
||
|
||
#endif
|