mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-10 01:40:17 +01:00
564 lines
15 KiB
C++
564 lines
15 KiB
C++
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
* http://www.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is Mozilla Communicator client code.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* Netscape Communications Corporation.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||
|
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
|
* of those above. If you wish to allow use of your version of this file only
|
||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
|
* use your version of this file under the terms of the MPL, indicate your
|
||
|
* decision by deleting the provisions above and replace them with the notice
|
||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
|
* the provisions above, a recipient may use your version of this file under
|
||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
#include "nsIServiceManager.h"
|
||
|
#include "nsICharsetConverterManager.h"
|
||
|
#include "nsUCSupport.h"
|
||
|
#include "nsString.h"
|
||
|
#include "nsIStringEnumerator.h"
|
||
|
#include "nsVoidArray.h"
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Global functions and data [declaration]
|
||
|
|
||
|
#define ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0]))
|
||
|
#define SMALL_BUFFER_SIZE 512
|
||
|
#define MED_BUFFER_SIZE 1024
|
||
|
#define BIG_BUFFER_SIZE 2048
|
||
|
|
||
|
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Class nsTestLog [declaration]
|
||
|
|
||
|
/**
|
||
|
* A Logging class for test programs.
|
||
|
*
|
||
|
* This simple test program will not trigger a component registration. So
|
||
|
* Mozilla has to be run once before running this, so that the necessary
|
||
|
* components will be registered. Also, please observe that the ContractID's are
|
||
|
* case sensitive now!
|
||
|
*
|
||
|
* @created 28/Mar/2000
|
||
|
* @author Catalin Rotaru [CATA]
|
||
|
*/
|
||
|
class nsTestLog
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
static const char * kTraceDelimiter;
|
||
|
|
||
|
nsCAutoString mTrace;
|
||
|
|
||
|
public:
|
||
|
|
||
|
void AddTrace(char * aTrace);
|
||
|
void DelTrace(char * aTrace);
|
||
|
void PrintError(char * aCall, int aError);
|
||
|
void PrintError(char * aCall, char * aMessage);
|
||
|
};
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Class nsTestUConv [declaration]
|
||
|
|
||
|
/**
|
||
|
* The main class of the program.
|
||
|
*
|
||
|
* XXX Create a very general set of "bug and regression" test cases and the
|
||
|
* one in TestTempBug()
|
||
|
* XXX Apply the new argument style (pointers) to the converters interfaces
|
||
|
*
|
||
|
* @created 28/Mar/2000
|
||
|
* @author Catalin Rotaru [CATA]
|
||
|
*/
|
||
|
class nsTestUConv
|
||
|
{
|
||
|
private:
|
||
|
|
||
|
nsTestLog mLog;
|
||
|
|
||
|
/**
|
||
|
* Run the built-in set of self tests for encoders.
|
||
|
*/
|
||
|
nsresult TestEncoders();
|
||
|
|
||
|
/**
|
||
|
* Run the built-in set of self tests for decoders.
|
||
|
*/
|
||
|
nsresult TestDecoders();
|
||
|
|
||
|
/**
|
||
|
* Run the built-in set of self tests for the CharsetManager.
|
||
|
*/
|
||
|
nsresult TestCharsetManager();
|
||
|
|
||
|
/**
|
||
|
* Display charset detectors and their attributes.
|
||
|
*/
|
||
|
nsresult DisplayDetectors();
|
||
|
|
||
|
/**
|
||
|
* Display charsets and their attributes.
|
||
|
*/
|
||
|
nsresult DisplayCharsets();
|
||
|
|
||
|
/**
|
||
|
* Run a temporary debug test. This method is ment as a placeholder when some
|
||
|
* quick debugging is needed.
|
||
|
*/
|
||
|
nsresult TestTempBug();
|
||
|
|
||
|
nsresult Encode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, char ** aDest,
|
||
|
char * aDestEnd, const nsAFlatCString& aCharset);
|
||
|
|
||
|
/**
|
||
|
* Bridge methods between the new argument style (poiters) and the old one
|
||
|
* (lengths). To be removed when the converter interfaces will switch to the
|
||
|
* new style.
|
||
|
*
|
||
|
* This wraps an encoder Convert() call.
|
||
|
*/
|
||
|
nsresult ConvertEncode(PRUnichar ** aSrc, PRUnichar * aSrcEnd, char ** aDest,
|
||
|
char * aDestEnd, nsIUnicodeEncoder * aEncoder);
|
||
|
|
||
|
/**
|
||
|
* This wraps an encoder Finish() call.
|
||
|
*/
|
||
|
nsresult FinishEncode(char ** aDest, char * aDestEnd,
|
||
|
nsIUnicodeEncoder * aEncoder);
|
||
|
|
||
|
void PrintSpaces(int aCount);
|
||
|
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Main method of the program.
|
||
|
*/
|
||
|
nsresult Main(int aArgC, char ** aArgV);
|
||
|
};
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Global functions and data [implementation]
|
||
|
|
||
|
int main(int argc, char ** argv)
|
||
|
{
|
||
|
nsTestUConv testObj;
|
||
|
nsresult res;
|
||
|
|
||
|
res = testObj.Main(argc, argv);
|
||
|
return (NS_FAILED(res));
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Class nsTestLog [implementation]
|
||
|
|
||
|
const char * nsTestLog::kTraceDelimiter = ".";
|
||
|
|
||
|
void nsTestLog::AddTrace(char * aTrace)
|
||
|
{
|
||
|
mTrace.Append(aTrace);
|
||
|
mTrace.Append(kTraceDelimiter);
|
||
|
}
|
||
|
|
||
|
void nsTestLog::DelTrace(char * aTrace)
|
||
|
{
|
||
|
mTrace.Truncate(mTrace.Length() - strlen(aTrace) - strlen(kTraceDelimiter));
|
||
|
}
|
||
|
|
||
|
void nsTestLog::PrintError(char * aCall, int aError)
|
||
|
{
|
||
|
const char * trace = mTrace.get();
|
||
|
printf("ERROR at %s%s code=0x%x.\n", trace, aCall, aError);
|
||
|
}
|
||
|
|
||
|
void nsTestLog::PrintError(char * aCall, char * aMessage)
|
||
|
{
|
||
|
const char * trace = mTrace.get();
|
||
|
printf("ERROR at %s%s reason: %s.\n", trace, aCall, aMessage);
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Class nsTestUConv [implementation]
|
||
|
|
||
|
nsresult nsTestUConv::TestEncoders()
|
||
|
{
|
||
|
char * trace = "TestEncoders";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
nsCOMPtr<nsICharsetConverterManager> ccMan =
|
||
|
do_GetService(kCharsetConverterManagerCID, &res);
|
||
|
if (NS_FAILED(res)) return res;
|
||
|
|
||
|
nsCOMPtr<nsIUTF8StringEnumerator> encoders;
|
||
|
res = ccMan->GetEncoderList(getter_AddRefs(encoders));
|
||
|
if (NS_FAILED(res)) return res;
|
||
|
|
||
|
PRUint32 encoderCount=0;
|
||
|
|
||
|
PRBool hasMore;
|
||
|
encoders->HasMore(&hasMore);
|
||
|
|
||
|
nsCAutoString charset;
|
||
|
while (hasMore) {
|
||
|
encoders->GetNext(charset);
|
||
|
|
||
|
encoders->HasMore(&hasMore);
|
||
|
}
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::TestDecoders()
|
||
|
{
|
||
|
char * trace = "TestDecoders";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
// XXX write me
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::TestCharsetManager()
|
||
|
{
|
||
|
char * trace = "TestCharsetManager";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
nsAutoString name;
|
||
|
nsCOMPtr<nsIAtom> csAtom;
|
||
|
|
||
|
nsCOMPtr<nsICharsetConverterManager> ccMan =
|
||
|
do_GetService(kCharsetConverterManagerCID, &res);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("NS_WITH_SERVICE", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::DisplayDetectors()
|
||
|
{
|
||
|
char * trace = "DisplayDetectors";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
nsCOMPtr<nsICharsetConverterManager> ccMan =
|
||
|
do_GetService(kCharsetConverterManagerCID, &res);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("NS_WITH_SERVICE", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// charset detectors
|
||
|
nsCOMPtr<nsIUTF8StringEnumerator> detectors;
|
||
|
|
||
|
res = ccMan->GetCharsetDetectorList(getter_AddRefs(detectors));
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("GetCharsetDetectorList()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
printf("***** Character Set Detectors *****\n");
|
||
|
|
||
|
PRBool hasMore;
|
||
|
detectors->HasMore(&hasMore);
|
||
|
while (hasMore) {
|
||
|
nsCAutoString detectorName;
|
||
|
res = detectors->GetNext(detectorName);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("GetNext()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
printf("%s", detectorName.get());
|
||
|
PrintSpaces(36 - detectorName.Length()); // align to hard coded column number
|
||
|
|
||
|
nsAutoString title;
|
||
|
res = ccMan->GetCharsetTitle(detectorName.get(), title);
|
||
|
if (NS_FAILED(res)) title.SetLength(0);
|
||
|
printf("\"%s\"\n", NS_LossyConvertUCS2toASCII(title).get());
|
||
|
}
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return NS_OK;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::DisplayCharsets()
|
||
|
{
|
||
|
char * trace = "DisplayCharsets";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
nsCOMPtr<nsICharsetConverterManager> ccMan =
|
||
|
do_GetService(kCharsetConverterManagerCID, &res);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("NS_WITH_SERVICE", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsCOMPtr<nsIUTF8StringEnumerator> decoders;
|
||
|
nsCOMPtr<nsIUTF8StringEnumerator> encoders;
|
||
|
|
||
|
res = ccMan->GetDecoderList(getter_AddRefs(decoders));
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("GetDecoderList()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
res = ccMan->GetEncoderList(getter_AddRefs(encoders));
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("GetEncoderList()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
|
||
|
printf("***** Character Sets *****\n");
|
||
|
|
||
|
PRUint32 encCount = 0, decCount = 0;
|
||
|
PRUint32 basicEncCount = 0, basicDecCount = 0;
|
||
|
|
||
|
nsCStringArray allCharsets;
|
||
|
|
||
|
nsCAutoString charset;
|
||
|
PRBool hasMore;
|
||
|
encoders->HasMore(&hasMore);
|
||
|
while (hasMore) {
|
||
|
res = encoders->GetNext(charset);
|
||
|
if (NS_SUCCEEDED(res))
|
||
|
allCharsets.AppendCString(charset);
|
||
|
|
||
|
encoders->HasMore(&hasMore);
|
||
|
}
|
||
|
|
||
|
nsAutoString prop, str;
|
||
|
PRUint32 count = allCharsets.Count();
|
||
|
for (PRUint32 i = 0; i < count; i++) {
|
||
|
|
||
|
const nsCString* charset = allCharsets[i];
|
||
|
printf("%s", charset->get());
|
||
|
PrintSpaces(24 - charset->Length()); // align to hard coded column number
|
||
|
|
||
|
|
||
|
nsCOMPtr<nsIUnicodeDecoder> dec = NULL;
|
||
|
res = ccMan->GetUnicodeDecoder(charset->get(), getter_AddRefs(dec));
|
||
|
if (NS_FAILED(res)) printf (" ");
|
||
|
else {
|
||
|
printf("D");
|
||
|
decCount++;
|
||
|
}
|
||
|
#ifdef NS_DEBUG
|
||
|
// show the "basic" decoder classes
|
||
|
if (dec) {
|
||
|
nsCOMPtr<nsIBasicDecoder> isBasic = do_QueryInterface(dec);
|
||
|
if (isBasic) {
|
||
|
basicDecCount++;
|
||
|
printf("b");
|
||
|
}
|
||
|
else printf(" ");
|
||
|
}
|
||
|
else printf(" ");
|
||
|
#endif
|
||
|
|
||
|
nsCOMPtr<nsIUnicodeEncoder> enc = NULL;
|
||
|
res = ccMan->GetUnicodeEncoder(charset->get(), getter_AddRefs(enc));
|
||
|
if (NS_FAILED(res)) printf (" ");
|
||
|
else {
|
||
|
printf("E");
|
||
|
encCount++;
|
||
|
}
|
||
|
|
||
|
#ifdef NS_DEBUG
|
||
|
if (enc) {
|
||
|
nsCOMPtr<nsIBasicEncoder> isBasic = do_QueryInterface(enc);
|
||
|
if (isBasic) {
|
||
|
basicEncCount++;
|
||
|
printf("b");
|
||
|
}
|
||
|
else printf(" ");
|
||
|
}
|
||
|
else printf(" ");
|
||
|
#endif
|
||
|
|
||
|
printf(" ");
|
||
|
|
||
|
prop.AssignLiteral(".notForBrowser");
|
||
|
res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
|
||
|
if ((dec != NULL) && (NS_FAILED(res))) printf ("B");
|
||
|
else printf("X");
|
||
|
|
||
|
prop.AssignLiteral(".notForComposer");
|
||
|
res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
|
||
|
if ((enc != NULL) && (NS_FAILED(res))) printf ("C");
|
||
|
else printf("X");
|
||
|
|
||
|
prop.AssignLiteral(".notForMailView");
|
||
|
res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
|
||
|
if ((dec != NULL) && (NS_FAILED(res))) printf ("V");
|
||
|
else printf("X");
|
||
|
|
||
|
prop.AssignLiteral(".notForMailEdit");
|
||
|
res = ccMan->GetCharsetData(charset->get(), prop.get(), str);
|
||
|
if ((enc != NULL) && (NS_FAILED(res))) printf ("E");
|
||
|
else printf("X");
|
||
|
|
||
|
printf("(%3d, %3d) ", encCount, decCount);
|
||
|
res = ccMan->GetCharsetTitle(charset->get(), str);
|
||
|
if (NS_FAILED(res)) str.SetLength(0);
|
||
|
NS_LossyConvertUCS2toASCII buff2(str);
|
||
|
printf(" \"%s\"\n", buff2.get());
|
||
|
}
|
||
|
|
||
|
printf("%u of %u decoders are basic (%d%%)\n",
|
||
|
basicDecCount, decCount, (basicDecCount * 100) / decCount);
|
||
|
|
||
|
printf("%u of %u encoders are basic (%d%%)\n",
|
||
|
basicEncCount, encCount, (basicEncCount * 100) / encCount);
|
||
|
mLog.DelTrace(trace);
|
||
|
return NS_OK;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::TestTempBug()
|
||
|
{
|
||
|
char * trace = "TestTempBug";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
NS_NAMED_LITERAL_CSTRING(charset, "ISO-2022-JP");
|
||
|
PRUnichar src[] = {0x0043, 0x004e, 0x0045, 0x0054, 0x0020, 0x004A, 0x0061,
|
||
|
0x0070, 0x0061, 0x006E, 0x0020, 0x7DE8, 0x96C6, 0x5C40};
|
||
|
PRUnichar * srcEnd = src + ARRAY_SIZE(src);
|
||
|
char dest[BIG_BUFFER_SIZE];
|
||
|
char * destEnd = dest + BIG_BUFFER_SIZE;
|
||
|
|
||
|
PRUnichar * p = src;
|
||
|
char * q = dest;
|
||
|
res = Encode(&p, srcEnd, &q, destEnd, charset);
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::Encode(PRUnichar ** aSrc, PRUnichar * aSrcEnd,
|
||
|
char ** aDest, char * aDestEnd,
|
||
|
const nsAFlatCString& aCharset)
|
||
|
{
|
||
|
char * trace = "Encode";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
nsCOMPtr<nsICharsetConverterManager> ccMan =
|
||
|
do_GetService(kCharsetConverterManagerCID, &res);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("NS_WITH_SERVICE", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsCOMPtr<nsIUnicodeEncoder> enc;
|
||
|
res = ccMan->GetUnicodeEncoder(aCharset.get(), getter_AddRefs(enc));
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("GetUnicodeEncoder()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
res = ConvertEncode(aSrc, aSrcEnd, aDest, aDestEnd, enc);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("Convert()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
res = FinishEncode(aDest, aDestEnd, enc);
|
||
|
if (NS_FAILED(res)) {
|
||
|
mLog.PrintError("Finish()", res);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::ConvertEncode(PRUnichar ** aSrc, PRUnichar * aSrcEnd,
|
||
|
char ** aDest, char * aDestEnd,
|
||
|
nsIUnicodeEncoder * aEncoder)
|
||
|
{
|
||
|
PRUnichar * src = (*aSrc);
|
||
|
char * dest = (*aDest);
|
||
|
PRInt32 srcLen = aSrcEnd - src;
|
||
|
PRInt32 destLen = aDestEnd - dest;
|
||
|
|
||
|
nsresult res = aEncoder->Convert(src, &srcLen, dest, &destLen);
|
||
|
|
||
|
(*aSrc) = src + srcLen;
|
||
|
(*aDest) = dest + destLen;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::FinishEncode(char ** aDest, char * aDestEnd,
|
||
|
nsIUnicodeEncoder * aEncoder)
|
||
|
{
|
||
|
char * dest = (*aDest);
|
||
|
PRInt32 destLen = aDestEnd - dest;
|
||
|
|
||
|
nsresult res = aEncoder->Finish(dest, &destLen);
|
||
|
|
||
|
(*aDest) = dest + destLen;
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
void nsTestUConv::PrintSpaces(int aCount)
|
||
|
{
|
||
|
for (int i = 0; i < aCount; i++) printf(" ");
|
||
|
}
|
||
|
|
||
|
nsresult nsTestUConv::Main(int aArgC, char ** aArgV)
|
||
|
{
|
||
|
char * trace = "Main";
|
||
|
mLog.AddTrace(trace);
|
||
|
nsresult res = NS_OK;
|
||
|
|
||
|
if (aArgC < 2) {
|
||
|
// no arguments were passed to the program, so we just run the self tests
|
||
|
res = TestCharsetManager();
|
||
|
if (NS_SUCCEEDED(res)) res = TestEncoders();
|
||
|
if (NS_SUCCEEDED(res)) res = TestDecoders();
|
||
|
} else if (!strcmp(aArgV[1], "-tempbug")) {
|
||
|
// we are testing a temporary bug
|
||
|
res = TestTempBug();
|
||
|
} else if (!strcmp(aArgV[1], "-display")) {
|
||
|
// display all the available data
|
||
|
res = DisplayDetectors();
|
||
|
if (NS_SUCCEEDED(res)) res = DisplayCharsets();
|
||
|
}
|
||
|
|
||
|
mLog.DelTrace(trace);
|
||
|
return res;
|
||
|
}
|